WindowManagerService.java revision d912e1f6a111fb33118d116bd72da1a328041bca
1/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.wm;
18
19import static android.view.WindowManager.LayoutParams.*;
20
21import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
22
23import android.app.AppOpsManager;
24import android.util.ArraySet;
25import android.util.TimeUtils;
26import android.view.IWindowId;
27
28import com.android.internal.app.IBatteryStats;
29import com.android.internal.policy.PolicyManager;
30import com.android.internal.policy.impl.PhoneWindowManager;
31import com.android.internal.util.FastPrintWriter;
32import com.android.internal.view.IInputContext;
33import com.android.internal.view.IInputMethodClient;
34import com.android.internal.view.IInputMethodManager;
35import com.android.internal.view.WindowManagerPolicyThread;
36import com.android.server.AttributeCache;
37import com.android.server.DisplayThread;
38import com.android.server.EventLogTags;
39import com.android.server.LocalServices;
40import com.android.server.UiThread;
41import com.android.server.Watchdog;
42import com.android.server.am.BatteryStatsService;
43import com.android.server.input.InputManagerService;
44import com.android.server.power.ShutdownThread;
45
46import android.Manifest;
47import android.app.ActivityManagerNative;
48import android.app.IActivityManager;
49import android.app.StatusBarManager;
50import android.app.admin.DevicePolicyManager;
51import android.animation.ValueAnimator;
52import android.content.BroadcastReceiver;
53import android.content.Context;
54import android.content.Intent;
55import android.content.IntentFilter;
56import android.content.pm.ActivityInfo;
57import android.content.pm.PackageManager;
58import android.content.res.CompatibilityInfo;
59import android.content.res.Configuration;
60import android.graphics.Bitmap;
61import android.graphics.Bitmap.Config;
62import android.graphics.Canvas;
63import android.graphics.Matrix;
64import android.graphics.PixelFormat;
65import android.graphics.Point;
66import android.graphics.Rect;
67import android.graphics.RectF;
68import android.graphics.Region;
69import android.hardware.display.DisplayManager;
70import android.hardware.display.DisplayManagerInternal;
71import android.os.Binder;
72import android.os.Bundle;
73import android.os.Debug;
74import android.os.Handler;
75import android.os.IBinder;
76import android.os.IRemoteCallback;
77import android.os.Looper;
78import android.os.Message;
79import android.os.Parcel;
80import android.os.ParcelFileDescriptor;
81import android.os.PowerManager;
82import android.os.PowerManagerInternal;
83import android.os.Process;
84import android.os.RemoteException;
85import android.os.ServiceManager;
86import android.os.StrictMode;
87import android.os.SystemClock;
88import android.os.SystemProperties;
89import android.os.Trace;
90import android.os.WorkSource;
91import android.provider.Settings;
92import android.util.DisplayMetrics;
93import android.util.EventLog;
94import android.util.FloatMath;
95import android.util.Log;
96import android.util.SparseArray;
97import android.util.Pair;
98import android.util.Slog;
99import android.util.SparseIntArray;
100import android.util.TypedValue;
101import android.view.Choreographer;
102import android.view.Display;
103import android.view.DisplayInfo;
104import android.view.Gravity;
105import android.view.IApplicationToken;
106import android.view.IInputFilter;
107import android.view.IMagnificationCallbacks;
108import android.view.IOnKeyguardExitResult;
109import android.view.IRotationWatcher;
110import android.view.IWindow;
111import android.view.IWindowManager;
112import android.view.IWindowSession;
113import android.view.InputChannel;
114import android.view.InputDevice;
115import android.view.InputEvent;
116import android.view.InputEventReceiver;
117import android.view.KeyEvent;
118import android.view.MagnificationSpec;
119import android.view.MotionEvent;
120import android.view.WindowManagerInternal;
121import android.view.Surface.OutOfResourcesException;
122import android.view.Surface;
123import android.view.SurfaceControl;
124import android.view.SurfaceSession;
125import android.view.View;
126import android.view.ViewTreeObserver;
127import android.view.WindowManager;
128import android.view.WindowManagerGlobal;
129import android.view.WindowManagerPolicy;
130import android.view.WindowManager.LayoutParams;
131import android.view.WindowManagerPolicy.FakeWindow;
132import android.view.WindowManagerPolicy.PointerEventListener;
133import android.view.animation.Animation;
134import android.view.animation.AnimationUtils;
135import android.view.animation.Transformation;
136
137import java.io.BufferedWriter;
138import java.io.DataInputStream;
139import java.io.File;
140import java.io.FileDescriptor;
141import java.io.FileInputStream;
142import java.io.FileNotFoundException;
143import java.io.IOException;
144import java.io.OutputStream;
145import java.io.OutputStreamWriter;
146import java.io.PrintWriter;
147import java.io.StringWriter;
148import java.net.Socket;
149import java.text.DateFormat;
150import java.util.ArrayList;
151import java.util.Date;
152import java.util.HashMap;
153import java.util.HashSet;
154import java.util.Iterator;
155import java.util.List;
156
157/** {@hide} */
158public class WindowManagerService extends IWindowManager.Stub
159        implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
160    static final String TAG = "WindowManager";
161    static final boolean DEBUG = false;
162    static final boolean DEBUG_ADD_REMOVE = false;
163    static final boolean DEBUG_FOCUS = false;
164    static final boolean DEBUG_FOCUS_LIGHT = DEBUG_FOCUS || false;
165    static final boolean DEBUG_ANIM = false;
166    static final boolean DEBUG_LAYOUT = false;
167    static final boolean DEBUG_RESIZE = false;
168    static final boolean DEBUG_LAYERS = false;
169    static final boolean DEBUG_INPUT = false;
170    static final boolean DEBUG_INPUT_METHOD = false;
171    static final boolean DEBUG_VISIBILITY = false;
172    static final boolean DEBUG_WINDOW_MOVEMENT = false;
173    static final boolean DEBUG_TOKEN_MOVEMENT = false;
174    static final boolean DEBUG_ORIENTATION = false;
175    static final boolean DEBUG_APP_ORIENTATION = false;
176    static final boolean DEBUG_CONFIGURATION = false;
177    static final boolean DEBUG_APP_TRANSITIONS = false;
178    static final boolean DEBUG_STARTING_WINDOW = false;
179    static final boolean DEBUG_REORDER = false;
180    static final boolean DEBUG_WALLPAPER = false;
181    static final boolean DEBUG_WALLPAPER_LIGHT = false || DEBUG_WALLPAPER;
182    static final boolean DEBUG_DRAG = false;
183    static final boolean DEBUG_SCREEN_ON = false;
184    static final boolean DEBUG_SCREENSHOT = false;
185    static final boolean DEBUG_BOOT = false;
186    static final boolean DEBUG_LAYOUT_REPEATS = true;
187    static final boolean DEBUG_SURFACE_TRACE = false;
188    static final boolean DEBUG_WINDOW_TRACE = false;
189    static final boolean DEBUG_TASK_MOVEMENT = false;
190    static final boolean DEBUG_STACK = false;
191    static final boolean DEBUG_DISPLAY = false;
192    static final boolean SHOW_SURFACE_ALLOC = false;
193    static final boolean SHOW_TRANSACTIONS = false;
194    static final boolean SHOW_LIGHT_TRANSACTIONS = false || SHOW_TRANSACTIONS;
195    static final boolean HIDE_STACK_CRAWLS = true;
196    static final int LAYOUT_REPEAT_THRESHOLD = 4;
197
198    static final boolean PROFILE_ORIENTATION = false;
199    static final boolean localLOGV = DEBUG;
200
201    /** How much to multiply the policy's type layer, to reserve room
202     * for multiple windows of the same type and Z-ordering adjustment
203     * with TYPE_LAYER_OFFSET. */
204    static final int TYPE_LAYER_MULTIPLIER = 10000;
205
206    /** Offset from TYPE_LAYER_MULTIPLIER for moving a group of windows above
207     * or below others in the same layer. */
208    static final int TYPE_LAYER_OFFSET = 1000;
209
210    /** How much to increment the layer for each window, to reserve room
211     * for effect surfaces between them.
212     */
213    static final int WINDOW_LAYER_MULTIPLIER = 5;
214
215    /**
216     * Dim surface layer is immediately below target window.
217     */
218    static final int LAYER_OFFSET_DIM = 1;
219
220    /**
221     * Blur surface layer is immediately below dim layer.
222     */
223    static final int LAYER_OFFSET_BLUR = 2;
224
225    /**
226     * FocusedStackFrame layer is immediately above focused window.
227     */
228    static final int LAYER_OFFSET_FOCUSED_STACK = 1;
229
230    /**
231     * Animation thumbnail is as far as possible below the window above
232     * the thumbnail (or in other words as far as possible above the window
233     * below it).
234     */
235    static final int LAYER_OFFSET_THUMBNAIL = WINDOW_LAYER_MULTIPLIER-1;
236
237    /**
238     * Layer at which to put the rotation freeze snapshot.
239     */
240    static final int FREEZE_LAYER = (TYPE_LAYER_MULTIPLIER * 200) + 1;
241
242    /**
243     * Layer at which to put the mask for emulated screen sizes.
244     */
245    static final int MASK_LAYER = TYPE_LAYER_MULTIPLIER * 200;
246
247    /** The maximum length we will accept for a loaded animation duration:
248     * this is 10 seconds.
249     */
250    static final int MAX_ANIMATION_DURATION = 10*1000;
251
252    /** Amount of time (in milliseconds) to animate the fade-in-out transition for
253     * compatible windows.
254     */
255    static final int DEFAULT_FADE_IN_OUT_DURATION = 400;
256
257    /** Amount of time (in milliseconds) to delay before declaring a window freeze timeout. */
258    static final int WINDOW_FREEZE_TIMEOUT_DURATION = 2000;
259
260    /** Amount of time (in milliseconds) to delay before declaring a starting window leaked. */
261    static final int STARTING_WINDOW_TIMEOUT_DURATION = 10000;
262
263    /**
264     * If true, the window manager will do its own custom freezing and general
265     * management of the screen during rotation.
266     */
267    static final boolean CUSTOM_SCREEN_ROTATION = true;
268
269    // Maximum number of milliseconds to wait for input devices to be enumerated before
270    // proceding with safe mode detection.
271    private static final int INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS = 1000;
272
273    // Default input dispatching timeout in nanoseconds.
274    static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L;
275
276    /** Minimum value for attachStack and resizeStack weight value */
277    public static final float STACK_WEIGHT_MIN = 0.2f;
278
279    /** Maximum value for attachStack and resizeStack weight value */
280    public static final float STACK_WEIGHT_MAX = 0.8f;
281
282    static final int UPDATE_FOCUS_NORMAL = 0;
283    static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1;
284    static final int UPDATE_FOCUS_PLACING_SURFACES = 2;
285    static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3;
286
287    private static final String SYSTEM_SECURE = "ro.secure";
288    private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
289
290    private static final String DENSITY_OVERRIDE = "ro.config.density_override";
291    private static final String SIZE_OVERRIDE = "ro.config.size_override";
292
293    private static final String SCREEN_CIRCULAR = "ro.display.circular";
294
295    private static final int MAX_SCREENSHOT_RETRIES = 3;
296
297    final private KeyguardDisableHandler mKeyguardDisableHandler;
298
299    final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
300        @Override
301        public void onReceive(Context context, Intent intent) {
302            final String action = intent.getAction();
303            if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) {
304                mKeyguardDisableHandler.sendEmptyMessage(
305                    KeyguardDisableHandler.KEYGUARD_POLICY_CHANGED);
306            }
307        }
308    };
309
310    // Current user when multi-user is enabled. Don't show windows of non-current user.
311    int mCurrentUserId;
312
313    final Context mContext;
314
315    final boolean mHaveInputMethods;
316
317    final boolean mAllowBootMessages;
318
319    final boolean mLimitedAlphaCompositing;
320
321    final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager();
322
323    final IActivityManager mActivityManager;
324
325    final IBatteryStats mBatteryStats;
326
327    final AppOpsManager mAppOps;
328
329    final DisplaySettings mDisplaySettings;
330
331    /**
332     * All currently active sessions with clients.
333     */
334    final HashSet<Session> mSessions = new HashSet<Session>();
335
336    /**
337     * Mapping from an IWindow IBinder to the server's Window object.
338     * This is also used as the lock for all of our state.
339     * NOTE: Never call into methods that lock ActivityManagerService while holding this object.
340     */
341    final HashMap<IBinder, WindowState> mWindowMap = new HashMap<IBinder, WindowState>();
342
343    /**
344     * Mapping from a token IBinder to a WindowToken object.
345     */
346    final HashMap<IBinder, WindowToken> mTokenMap = new HashMap<IBinder, WindowToken>();
347
348    /**
349     * List of window tokens that have finished starting their application,
350     * and now need to have the policy remove their windows.
351     */
352    final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<AppWindowToken>();
353
354    /**
355     * Fake windows added to the window manager.  Note: ordered from top to
356     * bottom, opposite of mWindows.
357     */
358    final ArrayList<FakeWindowImpl> mFakeWindows = new ArrayList<FakeWindowImpl>();
359
360    /**
361     * Windows that are being resized.  Used so we can tell the client about
362     * the resize after closing the transaction in which we resized the
363     * underlying surface.
364     */
365    final ArrayList<WindowState> mResizingWindows = new ArrayList<WindowState>();
366
367    /**
368     * Windows whose animations have ended and now must be removed.
369     */
370    final ArrayList<WindowState> mPendingRemove = new ArrayList<WindowState>();
371
372    /**
373     * Stacks whose animations have ended and whose tasks, apps, selves may now be removed.
374     */
375    final ArraySet<TaskStack> mPendingStacksRemove = new ArraySet<TaskStack>();
376
377    /**
378     * Used when processing mPendingRemove to avoid working on the original array.
379     */
380    WindowState[] mPendingRemoveTmp = new WindowState[20];
381
382    /**
383     * Windows whose surface should be destroyed.
384     */
385    final ArrayList<WindowState> mDestroySurface = new ArrayList<WindowState>();
386
387    /**
388     * Windows that have lost input focus and are waiting for the new
389     * focus window to be displayed before they are told about this.
390     */
391    ArrayList<WindowState> mLosingFocus = new ArrayList<WindowState>();
392
393    /**
394     * This is set when we have run out of memory, and will either be an empty
395     * list or contain windows that need to be force removed.
396     */
397    ArrayList<WindowState> mForceRemoves;
398
399    /**
400     * Windows that clients are waiting to have drawn.
401     */
402    ArrayList<Pair<WindowState, IRemoteCallback>> mWaitingForDrawn
403            = new ArrayList<Pair<WindowState, IRemoteCallback>>();
404
405    /**
406     * Windows that have called relayout() while we were running animations,
407     * so we need to tell when the animation is done.
408     */
409    final ArrayList<WindowState> mRelayoutWhileAnimating = new ArrayList<WindowState>();
410
411    /**
412     * Used when rebuilding window list to keep track of windows that have
413     * been removed.
414     */
415    WindowState[] mRebuildTmp = new WindowState[20];
416
417    IInputMethodManager mInputMethodManager;
418
419    DisplayMagnifier mDisplayMagnifier;
420
421    final SurfaceSession mFxSession;
422    Watermark mWatermark;
423    StrictModeFlash mStrictModeFlash;
424    CircularDisplayMask mCircularDisplayMask;
425    FocusedStackFrame mFocusedStackFrame;
426
427    int mFocusedStackLayer;
428
429    final float[] mTmpFloats = new float[9];
430    final Rect mTmpContentRect = new Rect();
431
432    boolean mDisplayReady;
433    boolean mSafeMode;
434    boolean mDisplayEnabled = false;
435    boolean mSystemBooted = false;
436    boolean mForceDisplayEnabled = false;
437    boolean mShowingBootMessages = false;
438
439    String mLastANRState;
440
441    /** All DisplayContents in the world, kept here */
442    SparseArray<DisplayContent> mDisplayContents = new SparseArray<DisplayContent>(2);
443
444    int mRotation = 0;
445    int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
446    boolean mAltOrientation = false;
447    class RotationWatcher {
448        IRotationWatcher watcher;
449        IBinder.DeathRecipient dr;
450        RotationWatcher(IRotationWatcher w, IBinder.DeathRecipient d) {
451            watcher = w;
452            dr = d;
453        }
454    }
455    ArrayList<RotationWatcher> mRotationWatchers = new ArrayList<RotationWatcher>();
456    int mDeferredRotationPauseCount;
457
458    int mSystemDecorLayer = 0;
459    final Rect mScreenRect = new Rect();
460
461    boolean mTraversalScheduled = false;
462    boolean mDisplayFrozen = false;
463    long mDisplayFreezeTime = 0;
464    int mLastDisplayFreezeDuration = 0;
465    Object mLastFinishedFreezeSource = null;
466    boolean mWaitingForConfig = false;
467    boolean mWindowsFreezingScreen = false;
468    boolean mClientFreezingScreen = false;
469    int mAppsFreezingScreen = 0;
470    int mLastWindowForcedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
471
472    int mLayoutSeq = 0;
473
474    int mLastStatusBarVisibility = 0;
475
476    // State while inside of layoutAndPlaceSurfacesLocked().
477    boolean mFocusMayChange;
478
479    Configuration mCurConfiguration = new Configuration();
480
481    // This is held as long as we have the screen frozen, to give us time to
482    // perform a rotation animation when turning off shows the lock screen which
483    // changes the orientation.
484    private final PowerManager.WakeLock mScreenFrozenLock;
485
486    final AppTransition mAppTransition;
487    boolean mStartingIconInTransition = false;
488    boolean mSkipAppTransitionAnimation = false;
489
490    final ArrayList<AppWindowToken> mOpeningApps = new ArrayList<AppWindowToken>();
491    final ArrayList<AppWindowToken> mClosingApps = new ArrayList<AppWindowToken>();
492
493    boolean mIsTouchDevice;
494
495    final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
496    final DisplayMetrics mRealDisplayMetrics = new DisplayMetrics();
497    final DisplayMetrics mTmpDisplayMetrics = new DisplayMetrics();
498    final DisplayMetrics mCompatDisplayMetrics = new DisplayMetrics();
499
500    final H mH = new H();
501
502    final Choreographer mChoreographer = Choreographer.getInstance();
503
504    WindowState mCurrentFocus = null;
505    WindowState mLastFocus = null;
506
507    /** This just indicates the window the input method is on top of, not
508     * necessarily the window its input is going to. */
509    WindowState mInputMethodTarget = null;
510
511    /** If true hold off on modifying the animation layer of mInputMethodTarget */
512    boolean mInputMethodTargetWaitingAnim;
513    int mInputMethodAnimLayerAdjustment;
514
515    WindowState mInputMethodWindow = null;
516    final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<WindowState>();
517
518    boolean mHardKeyboardAvailable;
519    boolean mHardKeyboardEnabled;
520    OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
521
522    final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>();
523
524    // If non-null, this is the currently visible window that is associated
525    // with the wallpaper.
526    WindowState mWallpaperTarget = null;
527    // If non-null, we are in the middle of animating from one wallpaper target
528    // to another, and this is the lower one in Z-order.
529    WindowState mLowerWallpaperTarget = null;
530    // If non-null, we are in the middle of animating from one wallpaper target
531    // to another, and this is the higher one in Z-order.
532    WindowState mUpperWallpaperTarget = null;
533    int mWallpaperAnimLayerAdjustment;
534    float mLastWallpaperX = -1;
535    float mLastWallpaperY = -1;
536    float mLastWallpaperXStep = -1;
537    float mLastWallpaperYStep = -1;
538    // This is set when we are waiting for a wallpaper to tell us it is done
539    // changing its scroll position.
540    WindowState mWaitingOnWallpaper;
541    // The last time we had a timeout when waiting for a wallpaper.
542    long mLastWallpaperTimeoutTime;
543    // We give a wallpaper up to 150ms to finish scrolling.
544    static final long WALLPAPER_TIMEOUT = 150;
545    // Time we wait after a timeout before trying to wait again.
546    static final long WALLPAPER_TIMEOUT_RECOVERY = 10000;
547    boolean mAnimateWallpaperWithTarget;
548
549    AppWindowToken mFocusedApp = null;
550
551    PowerManager mPowerManager;
552    PowerManagerInternal mPowerManagerInternal;
553
554    float mWindowAnimationScale = 1.0f;
555    float mTransitionAnimationScale = 1.0f;
556    float mAnimatorDurationScale = 1.0f;
557
558    final InputManagerService mInputManager;
559    final DisplayManagerInternal mDisplayManagerInternal;
560    final DisplayManager mDisplayManager;
561
562    // Who is holding the screen on.
563    Session mHoldingScreenOn;
564    PowerManager.WakeLock mHoldingScreenWakeLock;
565
566    boolean mTurnOnScreen;
567
568    DragState mDragState = null;
569
570    // For frozen screen animations.
571    int mExitAnimId, mEnterAnimId;
572
573    /** Pulled out of performLayoutAndPlaceSurfacesLockedInner in order to refactor into multiple
574     * methods. */
575    class LayoutFields {
576        static final int SET_UPDATE_ROTATION                = 1 << 0;
577        static final int SET_WALLPAPER_MAY_CHANGE           = 1 << 1;
578        static final int SET_FORCE_HIDING_CHANGED           = 1 << 2;
579        static final int SET_ORIENTATION_CHANGE_COMPLETE    = 1 << 3;
580        static final int SET_TURN_ON_SCREEN                 = 1 << 4;
581        static final int SET_WALLPAPER_ACTION_PENDING       = 1 << 5;
582
583        boolean mWallpaperForceHidingChanged = false;
584        boolean mWallpaperMayChange = false;
585        boolean mOrientationChangeComplete = true;
586        Object mLastWindowFreezeSource = null;
587        private Session mHoldScreen = null;
588        private boolean mObscured = false;
589        private boolean mSyswin = false;
590        private float mScreenBrightness = -1;
591        private float mButtonBrightness = -1;
592        private long mUserActivityTimeout = -1;
593        private boolean mUpdateRotation = false;
594        boolean mWallpaperActionPending = false;
595
596        // Set to true when the display contains content to show the user.
597        // When false, the display manager may choose to mirror or blank the display.
598        boolean mDisplayHasContent = false;
599
600        // Only set while traversing the default display based on its content.
601        // Affects the behavior of mirroring on secondary displays.
602        boolean mObscureApplicationContentOnSecondaryDisplays = false;
603    }
604    final LayoutFields mInnerFields = new LayoutFields();
605
606    boolean mAnimationScheduled;
607
608    /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this
609     * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */
610    private int mTransactionSequence;
611
612    /** Only do a maximum of 6 repeated layouts. After that quit */
613    private int mLayoutRepeatCount;
614
615    final WindowAnimator mAnimator;
616
617    SparseArray<Task> mTaskIdToTask = new SparseArray<Task>();
618
619    /** All of the TaskStacks in the window manager, unordered. For an ordered list call
620     * DisplayContent.getStacks(). */
621    SparseArray<TaskStack> mStackIdToStack = new SparseArray<TaskStack>();
622
623    private final PointerEventDispatcher mPointerEventDispatcher;
624
625    final class DragInputEventReceiver extends InputEventReceiver {
626        public DragInputEventReceiver(InputChannel inputChannel, Looper looper) {
627            super(inputChannel, looper);
628        }
629
630        @Override
631        public void onInputEvent(InputEvent event) {
632            boolean handled = false;
633            try {
634                if (event instanceof MotionEvent
635                        && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0
636                        && mDragState != null) {
637                    final MotionEvent motionEvent = (MotionEvent)event;
638                    boolean endDrag = false;
639                    final float newX = motionEvent.getRawX();
640                    final float newY = motionEvent.getRawY();
641
642                    switch (motionEvent.getAction()) {
643                    case MotionEvent.ACTION_DOWN: {
644                        if (DEBUG_DRAG) {
645                            Slog.w(TAG, "Unexpected ACTION_DOWN in drag layer");
646                        }
647                    } break;
648
649                    case MotionEvent.ACTION_MOVE: {
650                        synchronized (mWindowMap) {
651                            // move the surface and tell the involved window(s) where we are
652                            mDragState.notifyMoveLw(newX, newY);
653                        }
654                    } break;
655
656                    case MotionEvent.ACTION_UP: {
657                        if (DEBUG_DRAG) Slog.d(TAG, "Got UP on move channel; dropping at "
658                                + newX + "," + newY);
659                        synchronized (mWindowMap) {
660                            endDrag = mDragState.notifyDropLw(newX, newY);
661                        }
662                    } break;
663
664                    case MotionEvent.ACTION_CANCEL: {
665                        if (DEBUG_DRAG) Slog.d(TAG, "Drag cancelled!");
666                        endDrag = true;
667                    } break;
668                    }
669
670                    if (endDrag) {
671                        if (DEBUG_DRAG) Slog.d(TAG, "Drag ended; tearing down state");
672                        // tell all the windows that the drag has ended
673                        synchronized (mWindowMap) {
674                            mDragState.endDragLw();
675                        }
676                    }
677
678                    handled = true;
679                }
680            } catch (Exception e) {
681                Slog.e(TAG, "Exception caught by drag handleMotion", e);
682            } finally {
683                finishInputEvent(event, handled);
684            }
685        }
686    }
687
688    /**
689     * Whether the UI is currently running in touch mode (not showing
690     * navigational focus because the user is directly pressing the screen).
691     */
692    boolean mInTouchMode = true;
693
694    private ViewServer mViewServer;
695    private final ArrayList<WindowChangeListener> mWindowChangeListeners =
696        new ArrayList<WindowChangeListener>();
697    private boolean mWindowsChanged = false;
698
699    public interface WindowChangeListener {
700        public void windowsChanged();
701        public void focusChanged();
702    }
703
704    final Configuration mTempConfiguration = new Configuration();
705
706    // The desired scaling factor for compatible apps.
707    float mCompatibleScreenScale;
708
709    // If true, only the core apps and services are being launched because the device
710    // is in a special boot mode, such as being encrypted or waiting for a decryption password.
711    // For example, when this flag is true, there will be no wallpaper service.
712    final boolean mOnlyCore;
713
714    public static WindowManagerService main(final Context context,
715            final InputManagerService im,
716            final boolean haveInputMethods, final boolean showBootMsgs,
717            final boolean onlyCore) {
718        final WindowManagerService[] holder = new WindowManagerService[1];
719        DisplayThread.getHandler().runWithScissors(new Runnable() {
720            @Override
721            public void run() {
722                holder[0] = new WindowManagerService(context, im,
723                        haveInputMethods, showBootMsgs, onlyCore);
724            }
725        }, 0);
726        return holder[0];
727    }
728
729    private void initPolicy() {
730        UiThread.getHandler().runWithScissors(new Runnable() {
731            @Override
732            public void run() {
733                WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
734
735                mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
736                mAnimator.mAboveUniverseLayer = mPolicy.getAboveUniverseLayer()
737                        * TYPE_LAYER_MULTIPLIER
738                        + TYPE_LAYER_OFFSET;
739            }
740        }, 0);
741    }
742
743    private WindowManagerService(Context context, InputManagerService inputManager,
744            boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) {
745        mContext = context;
746        mHaveInputMethods = haveInputMethods;
747        mAllowBootMessages = showBootMsgs;
748        mOnlyCore = onlyCore;
749        mLimitedAlphaCompositing = context.getResources().getBoolean(
750                com.android.internal.R.bool.config_sf_limitedAlpha);
751        mInputManager = inputManager; // Must be before createDisplayContentLocked.
752        mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
753        mDisplaySettings = new DisplaySettings(context);
754        mDisplaySettings.readSettingsLocked();
755
756        mPointerEventDispatcher = new PointerEventDispatcher(mInputManager.monitorInput(TAG));
757
758        mFxSession = new SurfaceSession();
759        mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
760        Display[] displays = mDisplayManager.getDisplays();
761        for (Display display : displays) {
762            createDisplayContentLocked(display);
763        }
764
765        mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy);
766
767        mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
768        mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
769        mPowerManagerInternal.setPolicy(mPolicy); // TODO: register as local service instead
770        mScreenFrozenLock = mPowerManager.newWakeLock(
771                PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN");
772        mScreenFrozenLock.setReferenceCounted(false);
773
774        mAppTransition = new AppTransition(context, mH);
775
776        mActivityManager = ActivityManagerNative.getDefault();
777        mBatteryStats = BatteryStatsService.getService();
778        mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
779        mAppOps.startWatchingMode(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, null,
780                new AppOpsManager.OnOpChangedInternalListener() {
781                    @Override
782                    public void onOpChanged(int op, String packageName) {
783                        updateAppOpsState();
784                    }
785                }
786        );
787
788        // Get persisted window scale setting
789        mWindowAnimationScale = Settings.Global.getFloat(context.getContentResolver(),
790                Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
791        mTransitionAnimationScale = Settings.Global.getFloat(context.getContentResolver(),
792                Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
793        setAnimatorDurationScale(Settings.Global.getFloat(context.getContentResolver(),
794                Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScale));
795
796        // Track changes to DevicePolicyManager state so we can enable/disable keyguard.
797        IntentFilter filter = new IntentFilter();
798        filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
799        mContext.registerReceiver(mBroadcastReceiver, filter);
800
801        mHoldingScreenWakeLock = mPowerManager.newWakeLock(
802                PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG);
803        mHoldingScreenWakeLock.setReferenceCounted(false);
804
805        mAnimator = new WindowAnimator(this);
806
807        initPolicy();
808
809        // Add ourself to the Watchdog monitors.
810        Watchdog.getInstance().addMonitor(this);
811
812        SurfaceControl.openTransaction();
813        try {
814            createWatermarkInTransaction();
815            mFocusedStackFrame = new FocusedStackFrame(
816                    getDefaultDisplayContentLocked().getDisplay(), mFxSession);
817        } finally {
818            SurfaceControl.closeTransaction();
819        }
820
821        LocalServices.addService(WindowManagerInternal.class, new LocalService());
822        showCircularDisplayMaskIfNeeded();
823    }
824
825    public InputMonitor getInputMonitor() {
826        return mInputMonitor;
827    }
828
829    @Override
830    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
831            throws RemoteException {
832        try {
833            return super.onTransact(code, data, reply, flags);
834        } catch (RuntimeException e) {
835            // The window manager only throws security exceptions, so let's
836            // log all others.
837            if (!(e instanceof SecurityException)) {
838                Slog.wtf(TAG, "Window Manager Crash", e);
839            }
840            throw e;
841        }
842    }
843
844    private void placeWindowAfter(WindowState pos, WindowState window) {
845        final WindowList windows = pos.getWindowList();
846        final int i = windows.indexOf(pos);
847        if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
848            TAG, "Adding window " + window + " at "
849            + (i+1) + " of " + windows.size() + " (after " + pos + ")");
850        windows.add(i+1, window);
851        mWindowsChanged = true;
852    }
853
854    private void placeWindowBefore(WindowState pos, WindowState window) {
855        final WindowList windows = pos.getWindowList();
856        int i = windows.indexOf(pos);
857        if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
858            TAG, "Adding window " + window + " at "
859            + i + " of " + windows.size() + " (before " + pos + ")");
860        if (i < 0) {
861            Slog.w(TAG, "placeWindowBefore: Unable to find " + pos + " in " + windows);
862            i = 0;
863        }
864        windows.add(i, window);
865        mWindowsChanged = true;
866    }
867
868    //This method finds out the index of a window that has the same app token as
869    //win. used for z ordering the windows in mWindows
870    private int findIdxBasedOnAppTokens(WindowState win) {
871        WindowList windows = win.getWindowList();
872        for(int j = windows.size() - 1; j >= 0; j--) {
873            WindowState wentry = windows.get(j);
874            if(wentry.mAppToken == win.mAppToken) {
875                return j;
876            }
877        }
878        return -1;
879    }
880
881    /**
882     * Return the list of Windows from the passed token on the given Display.
883     * @param token The token with all the windows.
884     * @param displayContent The display we are interested in.
885     * @return List of windows from token that are on displayContent.
886     */
887    WindowList getTokenWindowsOnDisplay(WindowToken token, DisplayContent displayContent) {
888        final WindowList windowList = new WindowList();
889        final int count = token.windows.size();
890        for (int i = 0; i < count; i++) {
891            final WindowState win = token.windows.get(i);
892            if (win.getDisplayContent() == displayContent) {
893                windowList.add(win);
894            }
895        }
896        return windowList;
897    }
898
899    /**
900     * Recursive search through a WindowList and all of its windows' children.
901     * @param targetWin The window to search for.
902     * @param windows The list to search.
903     * @return The index of win in windows or of the window that is an ancestor of win.
904     */
905    private int indexOfWinInWindowList(WindowState targetWin, WindowList windows) {
906        for (int i = windows.size() - 1; i >= 0; i--) {
907            final WindowState w = windows.get(i);
908            if (w == targetWin) {
909                return i;
910            }
911            if (!w.mChildWindows.isEmpty()) {
912                if (indexOfWinInWindowList(targetWin, w.mChildWindows) >= 0) {
913                    return i;
914                }
915            }
916        }
917        return -1;
918    }
919
920    private int addAppWindowToListLocked(final WindowState win) {
921        final IWindow client = win.mClient;
922        final WindowToken token = win.mToken;
923        final DisplayContent displayContent = win.getDisplayContent();
924        if (displayContent == null) {
925            // It doesn't matter this display is going away.
926            return 0;
927        }
928
929        final WindowList windows = win.getWindowList();
930        final int N = windows.size();
931        WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent);
932        int tokenWindowsPos = 0;
933        int windowListPos = tokenWindowList.size();
934        if (!tokenWindowList.isEmpty()) {
935            // If this application has existing windows, we
936            // simply place the new window on top of them... but
937            // keep the starting window on top.
938            if (win.mAttrs.type == TYPE_BASE_APPLICATION) {
939                // Base windows go behind everything else.
940                WindowState lowestWindow = tokenWindowList.get(0);
941                placeWindowBefore(lowestWindow, win);
942                tokenWindowsPos = indexOfWinInWindowList(lowestWindow, token.windows);
943            } else {
944                AppWindowToken atoken = win.mAppToken;
945                WindowState lastWindow = tokenWindowList.get(windowListPos - 1);
946                if (atoken != null && lastWindow == atoken.startingWindow) {
947                    placeWindowBefore(lastWindow, win);
948                    tokenWindowsPos = indexOfWinInWindowList(lastWindow, token.windows);
949                } else {
950                    int newIdx = findIdxBasedOnAppTokens(win);
951                    //there is a window above this one associated with the same
952                    //apptoken note that the window could be a floating window
953                    //that was created later or a window at the top of the list of
954                    //windows associated with this token.
955                    if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG,
956                            "not Base app: Adding window " + win + " at " + (newIdx + 1) + " of " +
957                            N);
958                    windows.add(newIdx + 1, win);
959                    if (newIdx < 0) {
960                        // No window from token found on win's display.
961                        tokenWindowsPos = 0;
962                    } else {
963                        tokenWindowsPos = indexOfWinInWindowList(
964                                windows.get(newIdx), token.windows) + 1;
965                    }
966                    mWindowsChanged = true;
967                }
968            }
969            return tokenWindowsPos;
970        }
971
972        // No windows from this token on this display
973        if (localLOGV) Slog.v(TAG, "Figuring out where to add app window " + client.asBinder()
974                + " (token=" + token + ")");
975        // Figure out where the window should go, based on the
976        // order of applications.
977        WindowState pos = null;
978
979        final ArrayList<Task> tasks = displayContent.getTasks();
980        int taskNdx;
981        int tokenNdx = -1;
982        for (taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
983            AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
984            for (tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
985                final AppWindowToken t = tokens.get(tokenNdx);
986                if (t == token) {
987                    --tokenNdx;
988                    if (tokenNdx < 0) {
989                        --taskNdx;
990                        if (taskNdx >= 0) {
991                            tokenNdx = tasks.get(taskNdx).mAppTokens.size() - 1;
992                        }
993                    }
994                    break;
995                }
996
997                // We haven't reached the token yet; if this token
998                // is not going to the bottom and has windows on this display, we can
999                // use it as an anchor for when we do reach the token.
1000                tokenWindowList = getTokenWindowsOnDisplay(t, displayContent);
1001                if (!t.sendingToBottom && tokenWindowList.size() > 0) {
1002                    pos = tokenWindowList.get(0);
1003                }
1004            }
1005            if (tokenNdx >= 0) {
1006                // early exit
1007                break;
1008            }
1009        }
1010
1011        // We now know the index into the apps.  If we found
1012        // an app window above, that gives us the position; else
1013        // we need to look some more.
1014        if (pos != null) {
1015            // Move behind any windows attached to this one.
1016            WindowToken atoken = mTokenMap.get(pos.mClient.asBinder());
1017            if (atoken != null) {
1018                tokenWindowList =
1019                        getTokenWindowsOnDisplay(atoken, displayContent);
1020                final int NC = tokenWindowList.size();
1021                if (NC > 0) {
1022                    WindowState bottom = tokenWindowList.get(0);
1023                    if (bottom.mSubLayer < 0) {
1024                        pos = bottom;
1025                    }
1026                }
1027            }
1028            placeWindowBefore(pos, win);
1029            return tokenWindowsPos;
1030        }
1031
1032        // Continue looking down until we find the first
1033        // token that has windows on this display.
1034        for ( ; taskNdx >= 0; --taskNdx) {
1035            AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
1036            for ( ; tokenNdx >= 0; --tokenNdx) {
1037                final AppWindowToken t = tokens.get(tokenNdx);
1038                tokenWindowList = getTokenWindowsOnDisplay(t, displayContent);
1039                final int NW = tokenWindowList.size();
1040                if (NW > 0) {
1041                    pos = tokenWindowList.get(NW-1);
1042                    break;
1043                }
1044            }
1045            if (tokenNdx >= 0) {
1046                // found
1047                break;
1048            }
1049        }
1050
1051        if (pos != null) {
1052            // Move in front of any windows attached to this
1053            // one.
1054            WindowToken atoken = mTokenMap.get(pos.mClient.asBinder());
1055            if (atoken != null) {
1056                final int NC = atoken.windows.size();
1057                if (NC > 0) {
1058                    WindowState top = atoken.windows.get(NC-1);
1059                    if (top.mSubLayer >= 0) {
1060                        pos = top;
1061                    }
1062                }
1063            }
1064            placeWindowAfter(pos, win);
1065            return tokenWindowsPos;
1066        }
1067
1068        // Just search for the start of this layer.
1069        final int myLayer = win.mBaseLayer;
1070        int i;
1071        for (i = 0; i < N; i++) {
1072            WindowState w = windows.get(i);
1073            if (w.mBaseLayer > myLayer) {
1074                break;
1075            }
1076        }
1077        if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG,
1078                "Based on layer: Adding window " + win + " at " + i + " of " + N);
1079        windows.add(i, win);
1080        mWindowsChanged = true;
1081        return tokenWindowsPos;
1082    }
1083
1084    private void addFreeWindowToListLocked(final WindowState win) {
1085        final WindowList windows = win.getWindowList();
1086
1087        // Figure out where window should go, based on layer.
1088        final int myLayer = win.mBaseLayer;
1089        int i;
1090        for (i = windows.size() - 1; i >= 0; i--) {
1091            if (windows.get(i).mBaseLayer <= myLayer) {
1092                break;
1093            }
1094        }
1095        i++;
1096        if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG,
1097                "Free window: Adding window " + win + " at " + i + " of " + windows.size());
1098        windows.add(i, win);
1099        mWindowsChanged = true;
1100    }
1101
1102    private void addAttachedWindowToListLocked(final WindowState win, boolean addToToken) {
1103        final WindowToken token = win.mToken;
1104        final DisplayContent displayContent = win.getDisplayContent();
1105        if (displayContent == null) {
1106            return;
1107        }
1108        final WindowState attached = win.mAttachedWindow;
1109
1110        WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent);
1111
1112        // Figure out this window's ordering relative to the window
1113        // it is attached to.
1114        final int NA = tokenWindowList.size();
1115        final int sublayer = win.mSubLayer;
1116        int largestSublayer = Integer.MIN_VALUE;
1117        WindowState windowWithLargestSublayer = null;
1118        int i;
1119        for (i = 0; i < NA; i++) {
1120            WindowState w = tokenWindowList.get(i);
1121            final int wSublayer = w.mSubLayer;
1122            if (wSublayer >= largestSublayer) {
1123                largestSublayer = wSublayer;
1124                windowWithLargestSublayer = w;
1125            }
1126            if (sublayer < 0) {
1127                // For negative sublayers, we go below all windows
1128                // in the same sublayer.
1129                if (wSublayer >= sublayer) {
1130                    if (addToToken) {
1131                        if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
1132                        token.windows.add(i, win);
1133                    }
1134                    placeWindowBefore(wSublayer >= 0 ? attached : w, win);
1135                    break;
1136                }
1137            } else {
1138                // For positive sublayers, we go above all windows
1139                // in the same sublayer.
1140                if (wSublayer > sublayer) {
1141                    if (addToToken) {
1142                        if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
1143                        token.windows.add(i, win);
1144                    }
1145                    placeWindowBefore(w, win);
1146                    break;
1147                }
1148            }
1149        }
1150        if (i >= NA) {
1151            if (addToToken) {
1152                if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
1153                token.windows.add(win);
1154            }
1155            if (sublayer < 0) {
1156                placeWindowBefore(attached, win);
1157            } else {
1158                placeWindowAfter(largestSublayer >= 0
1159                                 ? windowWithLargestSublayer
1160                                 : attached,
1161                                 win);
1162            }
1163        }
1164    }
1165
1166    private void addWindowToListInOrderLocked(final WindowState win, boolean addToToken) {
1167        if (DEBUG_FOCUS_LIGHT) Slog.d(TAG, "addWindowToListInOrderLocked: win=" + win +
1168                " Callers=" + Debug.getCallers(4));
1169        if (win.mAttachedWindow == null) {
1170            final WindowToken token = win.mToken;
1171            int tokenWindowsPos = 0;
1172            if (token.appWindowToken != null) {
1173                tokenWindowsPos = addAppWindowToListLocked(win);
1174            } else {
1175                addFreeWindowToListLocked(win);
1176            }
1177            if (addToToken) {
1178                if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
1179                token.windows.add(tokenWindowsPos, win);
1180            }
1181        } else {
1182            addAttachedWindowToListLocked(win, addToToken);
1183        }
1184
1185        if (win.mAppToken != null && addToToken) {
1186            win.mAppToken.allAppWindows.add(win);
1187        }
1188    }
1189
1190    static boolean canBeImeTarget(WindowState w) {
1191        final int fl = w.mAttrs.flags
1192                & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM);
1193        if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM)
1194                || w.mAttrs.type == TYPE_APPLICATION_STARTING) {
1195            if (DEBUG_INPUT_METHOD) {
1196                Slog.i(TAG, "isVisibleOrAdding " + w + ": " + w.isVisibleOrAdding());
1197                if (!w.isVisibleOrAdding()) {
1198                    Slog.i(TAG, "  mSurface=" + w.mWinAnimator.mSurfaceControl
1199                            + " relayoutCalled=" + w.mRelayoutCalled + " viewVis=" + w.mViewVisibility
1200                            + " policyVis=" + w.mPolicyVisibility
1201                            + " policyVisAfterAnim=" + w.mPolicyVisibilityAfterAnim
1202                            + " attachHid=" + w.mAttachedHidden
1203                            + " exiting=" + w.mExiting + " destroying=" + w.mDestroying);
1204                    if (w.mAppToken != null) {
1205                        Slog.i(TAG, "  mAppToken.hiddenRequested=" + w.mAppToken.hiddenRequested);
1206                    }
1207                }
1208            }
1209            return w.isVisibleOrAdding();
1210        }
1211        return false;
1212    }
1213
1214    /**
1215     * Dig through the WindowStates and find the one that the Input Method will target.
1216     * @param willMove
1217     * @return The index+1 in mWindows of the discovered target.
1218     */
1219    int findDesiredInputMethodWindowIndexLocked(boolean willMove) {
1220        // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the
1221        // same display. Or even when the current IME/target are not on the same screen as the next
1222        // IME/target. For now only look for input windows on the main screen.
1223        WindowList windows = getDefaultWindowListLocked();
1224        WindowState w = null;
1225        int i;
1226        for (i = windows.size() - 1; i >= 0; --i) {
1227            WindowState win = windows.get(i);
1228
1229            if (DEBUG_INPUT_METHOD && willMove) Slog.i(TAG, "Checking window @" + i
1230                    + " " + win + " fl=0x" + Integer.toHexString(win.mAttrs.flags));
1231            if (canBeImeTarget(win)) {
1232                w = win;
1233                //Slog.i(TAG, "Putting input method here!");
1234
1235                // Yet more tricksyness!  If this window is a "starting"
1236                // window, we do actually want to be on top of it, but
1237                // it is not -really- where input will go.  So if the caller
1238                // is not actually looking to move the IME, look down below
1239                // for a real window to target...
1240                if (!willMove
1241                        && w.mAttrs.type == TYPE_APPLICATION_STARTING
1242                        && i > 0) {
1243                    WindowState wb = windows.get(i-1);
1244                    if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) {
1245                        i--;
1246                        w = wb;
1247                    }
1248                }
1249                break;
1250            }
1251        }
1252
1253        // Now w is either mWindows[0] or an IME (or null if mWindows is empty).
1254
1255        if (DEBUG_INPUT_METHOD && willMove) Slog.v(TAG, "Proposed new IME target: " + w);
1256
1257        // Now, a special case -- if the last target's window is in the
1258        // process of exiting, and is above the new target, keep on the
1259        // last target to avoid flicker.  Consider for example a Dialog with
1260        // the IME shown: when the Dialog is dismissed, we want to keep
1261        // the IME above it until it is completely gone so it doesn't drop
1262        // behind the dialog or its full-screen scrim.
1263        final WindowState curTarget = mInputMethodTarget;
1264        if (curTarget != null
1265                && curTarget.isDisplayedLw()
1266                && curTarget.isClosing()
1267                && (w == null || curTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer)) {
1268            if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Current target higher, not changing");
1269            return windows.indexOf(curTarget) + 1;
1270        }
1271
1272        if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Desired input method target="
1273                + w + " willMove=" + willMove);
1274
1275        if (willMove && w != null) {
1276            AppWindowToken token = curTarget == null ? null : curTarget.mAppToken;
1277            if (token != null) {
1278
1279                // Now some fun for dealing with window animations that
1280                // modify the Z order.  We need to look at all windows below
1281                // the current target that are in this app, finding the highest
1282                // visible one in layering.
1283                WindowState highestTarget = null;
1284                int highestPos = 0;
1285                if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) {
1286                    WindowList curWindows = curTarget.getWindowList();
1287                    int pos = curWindows.indexOf(curTarget);
1288                    while (pos >= 0) {
1289                        WindowState win = curWindows.get(pos);
1290                        if (win.mAppToken != token) {
1291                            break;
1292                        }
1293                        if (!win.mRemoved) {
1294                            if (highestTarget == null || win.mWinAnimator.mAnimLayer >
1295                                    highestTarget.mWinAnimator.mAnimLayer) {
1296                                highestTarget = win;
1297                                highestPos = pos;
1298                            }
1299                        }
1300                        pos--;
1301                    }
1302                }
1303
1304                if (highestTarget != null) {
1305                    if (DEBUG_INPUT_METHOD) Slog.v(TAG, mAppTransition + " " + highestTarget
1306                            + " animating=" + highestTarget.mWinAnimator.isAnimating()
1307                            + " layer=" + highestTarget.mWinAnimator.mAnimLayer
1308                            + " new layer=" + w.mWinAnimator.mAnimLayer);
1309
1310                    if (mAppTransition.isTransitionSet()) {
1311                        // If we are currently setting up for an animation,
1312                        // hold everything until we can find out what will happen.
1313                        mInputMethodTargetWaitingAnim = true;
1314                        mInputMethodTarget = highestTarget;
1315                        return highestPos + 1;
1316                    } else if (highestTarget.mWinAnimator.isAnimating() &&
1317                            highestTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer) {
1318                        // If the window we are currently targeting is involved
1319                        // with an animation, and it is on top of the next target
1320                        // we will be over, then hold off on moving until
1321                        // that is done.
1322                        mInputMethodTargetWaitingAnim = true;
1323                        mInputMethodTarget = highestTarget;
1324                        return highestPos + 1;
1325                    }
1326                }
1327            }
1328        }
1329
1330        //Slog.i(TAG, "Placing input method @" + (i+1));
1331        if (w != null) {
1332            if (willMove) {
1333                if (DEBUG_INPUT_METHOD) Slog.w(TAG, "Moving IM target from " + curTarget + " to "
1334                        + w + (HIDE_STACK_CRAWLS ? "" : " Callers=" + Debug.getCallers(4)));
1335                mInputMethodTarget = w;
1336                mInputMethodTargetWaitingAnim = false;
1337                if (w.mAppToken != null) {
1338                    setInputMethodAnimLayerAdjustment(w.mAppToken.mAppAnimator.animLayerAdjustment);
1339                } else {
1340                    setInputMethodAnimLayerAdjustment(0);
1341                }
1342            }
1343            return i+1;
1344        }
1345        if (willMove) {
1346            if (DEBUG_INPUT_METHOD) Slog.w(TAG, "Moving IM target from " + curTarget + " to null."
1347                    + (HIDE_STACK_CRAWLS ? "" : " Callers=" + Debug.getCallers(4)));
1348            mInputMethodTarget = null;
1349            setInputMethodAnimLayerAdjustment(0);
1350        }
1351        return -1;
1352    }
1353
1354    void addInputMethodWindowToListLocked(WindowState win) {
1355        int pos = findDesiredInputMethodWindowIndexLocked(true);
1356        if (pos >= 0) {
1357            win.mTargetAppToken = mInputMethodTarget.mAppToken;
1358            if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
1359                    TAG, "Adding input method window " + win + " at " + pos);
1360            // TODO(multidisplay): IMEs are only supported on the default display.
1361            getDefaultWindowListLocked().add(pos, win);
1362            mWindowsChanged = true;
1363            moveInputMethodDialogsLocked(pos+1);
1364            return;
1365        }
1366        win.mTargetAppToken = null;
1367        addWindowToListInOrderLocked(win, true);
1368        moveInputMethodDialogsLocked(pos);
1369    }
1370
1371    void setInputMethodAnimLayerAdjustment(int adj) {
1372        if (DEBUG_LAYERS) Slog.v(TAG, "Setting im layer adj to " + adj);
1373        mInputMethodAnimLayerAdjustment = adj;
1374        WindowState imw = mInputMethodWindow;
1375        if (imw != null) {
1376            imw.mWinAnimator.mAnimLayer = imw.mLayer + adj;
1377            if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw
1378                    + " anim layer: " + imw.mWinAnimator.mAnimLayer);
1379            int wi = imw.mChildWindows.size();
1380            while (wi > 0) {
1381                wi--;
1382                WindowState cw = imw.mChildWindows.get(wi);
1383                cw.mWinAnimator.mAnimLayer = cw.mLayer + adj;
1384                if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + cw
1385                        + " anim layer: " + cw.mWinAnimator.mAnimLayer);
1386            }
1387        }
1388        int di = mInputMethodDialogs.size();
1389        while (di > 0) {
1390            di --;
1391            imw = mInputMethodDialogs.get(di);
1392            imw.mWinAnimator.mAnimLayer = imw.mLayer + adj;
1393            if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw
1394                    + " anim layer: " + imw.mWinAnimator.mAnimLayer);
1395        }
1396    }
1397
1398    private int tmpRemoveWindowLocked(int interestingPos, WindowState win) {
1399        WindowList windows = win.getWindowList();
1400        int wpos = windows.indexOf(win);
1401        if (wpos >= 0) {
1402            if (wpos < interestingPos) interestingPos--;
1403            if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing at " + wpos + ": " + win);
1404            windows.remove(wpos);
1405            mWindowsChanged = true;
1406            int NC = win.mChildWindows.size();
1407            while (NC > 0) {
1408                NC--;
1409                WindowState cw = win.mChildWindows.get(NC);
1410                int cpos = windows.indexOf(cw);
1411                if (cpos >= 0) {
1412                    if (cpos < interestingPos) interestingPos--;
1413                    if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing child at "
1414                            + cpos + ": " + cw);
1415                    windows.remove(cpos);
1416                }
1417            }
1418        }
1419        return interestingPos;
1420    }
1421
1422    private void reAddWindowToListInOrderLocked(WindowState win) {
1423        addWindowToListInOrderLocked(win, false);
1424        // This is a hack to get all of the child windows added as well
1425        // at the right position.  Child windows should be rare and
1426        // this case should be rare, so it shouldn't be that big a deal.
1427        WindowList windows = win.getWindowList();
1428        int wpos = windows.indexOf(win);
1429        if (wpos >= 0) {
1430            if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "ReAdd removing from " + wpos + ": " + win);
1431            windows.remove(wpos);
1432            mWindowsChanged = true;
1433            reAddWindowLocked(wpos, win);
1434        }
1435    }
1436
1437    void logWindowList(final WindowList windows, String prefix) {
1438        int N = windows.size();
1439        while (N > 0) {
1440            N--;
1441            Slog.v(TAG, prefix + "#" + N + ": " + windows.get(N));
1442        }
1443    }
1444
1445    void moveInputMethodDialogsLocked(int pos) {
1446        ArrayList<WindowState> dialogs = mInputMethodDialogs;
1447
1448        // TODO(multidisplay): IMEs are only supported on the default display.
1449        WindowList windows = getDefaultWindowListLocked();
1450        final int N = dialogs.size();
1451        if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Removing " + N + " dialogs w/pos=" + pos);
1452        for (int i=0; i<N; i++) {
1453            pos = tmpRemoveWindowLocked(pos, dialogs.get(i));
1454        }
1455        if (DEBUG_INPUT_METHOD) {
1456            Slog.v(TAG, "Window list w/pos=" + pos);
1457            logWindowList(windows, "  ");
1458        }
1459
1460        if (pos >= 0) {
1461            final AppWindowToken targetAppToken = mInputMethodTarget.mAppToken;
1462            if (pos < windows.size()) {
1463                WindowState wp = windows.get(pos);
1464                if (wp == mInputMethodWindow) {
1465                    pos++;
1466                }
1467            }
1468            if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Adding " + N + " dialogs at pos=" + pos);
1469            for (int i=0; i<N; i++) {
1470                WindowState win = dialogs.get(i);
1471                win.mTargetAppToken = targetAppToken;
1472                pos = reAddWindowLocked(pos, win);
1473            }
1474            if (DEBUG_INPUT_METHOD) {
1475                Slog.v(TAG, "Final window list:");
1476                logWindowList(windows, "  ");
1477            }
1478            return;
1479        }
1480        for (int i=0; i<N; i++) {
1481            WindowState win = dialogs.get(i);
1482            win.mTargetAppToken = null;
1483            reAddWindowToListInOrderLocked(win);
1484            if (DEBUG_INPUT_METHOD) {
1485                Slog.v(TAG, "No IM target, final list:");
1486                logWindowList(windows, "  ");
1487            }
1488        }
1489    }
1490
1491    boolean moveInputMethodWindowsIfNeededLocked(boolean needAssignLayers) {
1492        final WindowState imWin = mInputMethodWindow;
1493        final int DN = mInputMethodDialogs.size();
1494        if (imWin == null && DN == 0) {
1495            return false;
1496        }
1497
1498        // TODO(multidisplay): IMEs are only supported on the default display.
1499        WindowList windows = getDefaultWindowListLocked();
1500
1501        int imPos = findDesiredInputMethodWindowIndexLocked(true);
1502        if (imPos >= 0) {
1503            // In this case, the input method windows are to be placed
1504            // immediately above the window they are targeting.
1505
1506            // First check to see if the input method windows are already
1507            // located here, and contiguous.
1508            final int N = windows.size();
1509            WindowState firstImWin = imPos < N
1510                    ? windows.get(imPos) : null;
1511
1512            // Figure out the actual input method window that should be
1513            // at the bottom of their stack.
1514            WindowState baseImWin = imWin != null
1515                    ? imWin : mInputMethodDialogs.get(0);
1516            if (baseImWin.mChildWindows.size() > 0) {
1517                WindowState cw = baseImWin.mChildWindows.get(0);
1518                if (cw.mSubLayer < 0) baseImWin = cw;
1519            }
1520
1521            if (firstImWin == baseImWin) {
1522                // The windows haven't moved...  but are they still contiguous?
1523                // First find the top IM window.
1524                int pos = imPos+1;
1525                while (pos < N) {
1526                    if (!(windows.get(pos)).mIsImWindow) {
1527                        break;
1528                    }
1529                    pos++;
1530                }
1531                pos++;
1532                // Now there should be no more input method windows above.
1533                while (pos < N) {
1534                    if ((windows.get(pos)).mIsImWindow) {
1535                        break;
1536                    }
1537                    pos++;
1538                }
1539                if (pos >= N) {
1540                    // Z order is good.
1541                    // The IM target window may be changed, so update the mTargetAppToken.
1542                    if (imWin != null) {
1543                        imWin.mTargetAppToken = mInputMethodTarget.mAppToken;
1544                    }
1545                    return false;
1546                }
1547            }
1548
1549            if (imWin != null) {
1550                if (DEBUG_INPUT_METHOD) {
1551                    Slog.v(TAG, "Moving IM from " + imPos);
1552                    logWindowList(windows, "  ");
1553                }
1554                imPos = tmpRemoveWindowLocked(imPos, imWin);
1555                if (DEBUG_INPUT_METHOD) {
1556                    Slog.v(TAG, "List after removing with new pos " + imPos + ":");
1557                    logWindowList(windows, "  ");
1558                }
1559                imWin.mTargetAppToken = mInputMethodTarget.mAppToken;
1560                reAddWindowLocked(imPos, imWin);
1561                if (DEBUG_INPUT_METHOD) {
1562                    Slog.v(TAG, "List after moving IM to " + imPos + ":");
1563                    logWindowList(windows, "  ");
1564                }
1565                if (DN > 0) moveInputMethodDialogsLocked(imPos+1);
1566            } else {
1567                moveInputMethodDialogsLocked(imPos);
1568            }
1569
1570        } else {
1571            // In this case, the input method windows go in a fixed layer,
1572            // because they aren't currently associated with a focus window.
1573
1574            if (imWin != null) {
1575                if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Moving IM from " + imPos);
1576                tmpRemoveWindowLocked(0, imWin);
1577                imWin.mTargetAppToken = null;
1578                reAddWindowToListInOrderLocked(imWin);
1579                if (DEBUG_INPUT_METHOD) {
1580                    Slog.v(TAG, "List with no IM target:");
1581                    logWindowList(windows, "  ");
1582                }
1583                if (DN > 0) moveInputMethodDialogsLocked(-1);
1584            } else {
1585                moveInputMethodDialogsLocked(-1);
1586            }
1587
1588        }
1589
1590        if (needAssignLayers) {
1591            assignLayersLocked(windows);
1592        }
1593
1594        return true;
1595    }
1596
1597    final boolean isWallpaperVisible(WindowState wallpaperTarget) {
1598        if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured="
1599                + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??")
1600                + " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null)
1601                        ? wallpaperTarget.mAppToken.mAppAnimator.animation : null)
1602                + " upper=" + mUpperWallpaperTarget
1603                + " lower=" + mLowerWallpaperTarget);
1604        return (wallpaperTarget != null
1605                        && (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null
1606                                && wallpaperTarget.mAppToken.mAppAnimator.animation != null)))
1607                || mUpperWallpaperTarget != null
1608                || mLowerWallpaperTarget != null;
1609    }
1610
1611    static final int ADJUST_WALLPAPER_LAYERS_CHANGED = 1<<1;
1612    static final int ADJUST_WALLPAPER_VISIBILITY_CHANGED = 1<<2;
1613
1614    int adjustWallpaperWindowsLocked() {
1615        mInnerFields.mWallpaperMayChange = false;
1616        boolean targetChanged = false;
1617
1618        // TODO(multidisplay): Wallpapers on main screen only.
1619        final DisplayInfo displayInfo = getDefaultDisplayContentLocked().getDisplayInfo();
1620        final int dw = displayInfo.logicalWidth;
1621        final int dh = displayInfo.logicalHeight;
1622
1623        // First find top-most window that has asked to be on top of the
1624        // wallpaper; all wallpapers go behind it.
1625        final WindowList windows = getDefaultWindowListLocked();
1626        int N = windows.size();
1627        WindowState w = null;
1628        WindowState foundW = null;
1629        int foundI = 0;
1630        WindowState topCurW = null;
1631        int topCurI = 0;
1632        int windowDetachedI = -1;
1633        int i = N;
1634        while (i > 0) {
1635            i--;
1636            w = windows.get(i);
1637            if ((w.mAttrs.type == TYPE_WALLPAPER)) {
1638                if (topCurW == null) {
1639                    topCurW = w;
1640                    topCurI = i;
1641                }
1642                continue;
1643            }
1644            topCurW = null;
1645            if (w != mAnimator.mWindowDetachedWallpaper && w.mAppToken != null) {
1646                // If this window's app token is hidden and not animating,
1647                // it is of no interest to us.
1648                if (w.mAppToken.hidden && w.mAppToken.mAppAnimator.animation == null) {
1649                    if (DEBUG_WALLPAPER) Slog.v(TAG,
1650                            "Skipping hidden and not animating token: " + w);
1651                    continue;
1652                }
1653            }
1654            if (DEBUG_WALLPAPER) Slog.v(TAG, "Win #" + i + " " + w + ": isOnScreen="
1655                    + w.isOnScreen() + " mDrawState=" + w.mWinAnimator.mDrawState);
1656            if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0 && w.isOnScreen()
1657                    && (mWallpaperTarget == w || w.isDrawFinishedLw())) {
1658                if (DEBUG_WALLPAPER) Slog.v(TAG,
1659                        "Found wallpaper target: #" + i + "=" + w);
1660                foundW = w;
1661                foundI = i;
1662                if (w == mWallpaperTarget && w.mWinAnimator.isAnimating()) {
1663                    // The current wallpaper target is animating, so we'll
1664                    // look behind it for another possible target and figure
1665                    // out what is going on below.
1666                    if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w
1667                            + ": token animating, looking behind.");
1668                    continue;
1669                }
1670                break;
1671            } else if (w == mAnimator.mWindowDetachedWallpaper) {
1672                windowDetachedI = i;
1673            }
1674        }
1675
1676        if (foundW == null && windowDetachedI >= 0) {
1677            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
1678                    "Found animating detached wallpaper activity: #" + i + "=" + w);
1679            foundW = w;
1680            foundI = windowDetachedI;
1681        }
1682
1683        if (mWallpaperTarget != foundW
1684                && (mLowerWallpaperTarget == null || mLowerWallpaperTarget != foundW)) {
1685            if (DEBUG_WALLPAPER_LIGHT) {
1686                Slog.v(TAG, "New wallpaper target: " + foundW
1687                        + " oldTarget: " + mWallpaperTarget);
1688            }
1689
1690            mLowerWallpaperTarget = null;
1691            mUpperWallpaperTarget = null;
1692
1693            WindowState oldW = mWallpaperTarget;
1694            mWallpaperTarget = foundW;
1695            targetChanged = true;
1696
1697            // Now what is happening...  if the current and new targets are
1698            // animating, then we are in our super special mode!
1699            if (foundW != null && oldW != null) {
1700                boolean oldAnim = oldW.isAnimatingLw();
1701                boolean foundAnim = foundW.isAnimatingLw();
1702                if (DEBUG_WALLPAPER_LIGHT) {
1703                    Slog.v(TAG, "New animation: " + foundAnim
1704                            + " old animation: " + oldAnim);
1705                }
1706                if (foundAnim && oldAnim) {
1707                    int oldI = windows.indexOf(oldW);
1708                    if (DEBUG_WALLPAPER_LIGHT) {
1709                        Slog.v(TAG, "New i: " + foundI + " old i: " + oldI);
1710                    }
1711                    if (oldI >= 0) {
1712                        if (DEBUG_WALLPAPER_LIGHT) {
1713                            Slog.v(TAG, "Animating wallpapers: old#" + oldI
1714                                    + "=" + oldW + "; new#" + foundI
1715                                    + "=" + foundW);
1716                        }
1717
1718                        // Set the new target correctly.
1719                        if (foundW.mAppToken != null && foundW.mAppToken.hiddenRequested) {
1720                            if (DEBUG_WALLPAPER_LIGHT) {
1721                                Slog.v(TAG, "Old wallpaper still the target.");
1722                            }
1723                            mWallpaperTarget = oldW;
1724                            foundW = oldW;
1725                            foundI = oldI;
1726                        }
1727                        // Now set the upper and lower wallpaper targets
1728                        // correctly, and make sure that we are positioning
1729                        // the wallpaper below the lower.
1730                        else if (foundI > oldI) {
1731                            // The new target is on top of the old one.
1732                            if (DEBUG_WALLPAPER_LIGHT) {
1733                                Slog.v(TAG, "Found target above old target.");
1734                            }
1735                            mUpperWallpaperTarget = foundW;
1736                            mLowerWallpaperTarget = oldW;
1737                            foundW = oldW;
1738                            foundI = oldI;
1739                        } else {
1740                            // The new target is below the old one.
1741                            if (DEBUG_WALLPAPER_LIGHT) {
1742                                Slog.v(TAG, "Found target below old target.");
1743                            }
1744                            mUpperWallpaperTarget = oldW;
1745                            mLowerWallpaperTarget = foundW;
1746                        }
1747                    }
1748                }
1749            }
1750
1751        } else if (mLowerWallpaperTarget != null) {
1752            // Is it time to stop animating?
1753            if (!mLowerWallpaperTarget.isAnimatingLw() || !mUpperWallpaperTarget.isAnimatingLw()) {
1754                if (DEBUG_WALLPAPER_LIGHT) {
1755                    Slog.v(TAG, "No longer animating wallpaper targets!");
1756                }
1757                mLowerWallpaperTarget = null;
1758                mUpperWallpaperTarget = null;
1759                mWallpaperTarget = foundW;
1760                targetChanged = true;
1761            }
1762        }
1763
1764        boolean visible = foundW != null;
1765        if (visible) {
1766            // The window is visible to the compositor...  but is it visible
1767            // to the user?  That is what the wallpaper cares about.
1768            visible = isWallpaperVisible(foundW);
1769            if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper visibility: " + visible);
1770
1771            // If the wallpaper target is animating, we may need to copy
1772            // its layer adjustment.  Only do this if we are not transfering
1773            // between two wallpaper targets.
1774            mWallpaperAnimLayerAdjustment =
1775                    (mLowerWallpaperTarget == null && foundW.mAppToken != null)
1776                    ? foundW.mAppToken.mAppAnimator.animLayerAdjustment : 0;
1777
1778            final int maxLayer = mPolicy.getMaxWallpaperLayer()
1779                    * TYPE_LAYER_MULTIPLIER
1780                    + TYPE_LAYER_OFFSET;
1781
1782            // Now w is the window we are supposed to be behind...  but we
1783            // need to be sure to also be behind any of its attached windows,
1784            // AND any starting window associated with it, AND below the
1785            // maximum layer the policy allows for wallpapers.
1786            while (foundI > 0) {
1787                WindowState wb = windows.get(foundI-1);
1788                if (wb.mBaseLayer < maxLayer &&
1789                        wb.mAttachedWindow != foundW &&
1790                        (foundW.mAttachedWindow == null ||
1791                                wb.mAttachedWindow != foundW.mAttachedWindow) &&
1792                        (wb.mAttrs.type != TYPE_APPLICATION_STARTING ||
1793                                foundW.mToken == null || wb.mToken != foundW.mToken)) {
1794                    // This window is not related to the previous one in any
1795                    // interesting way, so stop here.
1796                    break;
1797                }
1798                foundW = wb;
1799                foundI--;
1800            }
1801        } else {
1802            if (DEBUG_WALLPAPER) Slog.v(TAG, "No wallpaper target");
1803        }
1804
1805        if (foundW == null && topCurW != null) {
1806            // There is no wallpaper target, so it goes at the bottom.
1807            // We will assume it is the same place as last time, if known.
1808            foundW = topCurW;
1809            foundI = topCurI+1;
1810        } else {
1811            // Okay i is the position immediately above the wallpaper.  Look at
1812            // what is below it for later.
1813            foundW = foundI > 0 ? windows.get(foundI-1) : null;
1814        }
1815
1816        if (visible) {
1817            if (mWallpaperTarget.mWallpaperX >= 0) {
1818                mLastWallpaperX = mWallpaperTarget.mWallpaperX;
1819                mLastWallpaperXStep = mWallpaperTarget.mWallpaperXStep;
1820            }
1821            if (mWallpaperTarget.mWallpaperY >= 0) {
1822                mLastWallpaperY = mWallpaperTarget.mWallpaperY;
1823                mLastWallpaperYStep = mWallpaperTarget.mWallpaperYStep;
1824            }
1825        }
1826
1827        // Start stepping backwards from here, ensuring that our wallpaper windows
1828        // are correctly placed.
1829        int changed = 0;
1830        int curTokenIndex = mWallpaperTokens.size();
1831        while (curTokenIndex > 0) {
1832            curTokenIndex--;
1833            WindowToken token = mWallpaperTokens.get(curTokenIndex);
1834            if (token.hidden == visible) {
1835                if (DEBUG_WALLPAPER_LIGHT) Slog.d(TAG,
1836                        "Wallpaper token " + token + " hidden=" + !visible);
1837                changed |= ADJUST_WALLPAPER_VISIBILITY_CHANGED;
1838                token.hidden = !visible;
1839                // Need to do a layout to ensure the wallpaper now has the
1840                // correct size.
1841                getDefaultDisplayContentLocked().layoutNeeded = true;
1842            }
1843
1844            int curWallpaperIndex = token.windows.size();
1845            while (curWallpaperIndex > 0) {
1846                curWallpaperIndex--;
1847                WindowState wallpaper = token.windows.get(curWallpaperIndex);
1848
1849                if (visible) {
1850                    updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
1851                }
1852
1853                // First, make sure the client has the current visibility
1854                // state.
1855                dispatchWallpaperVisibility(wallpaper, visible);
1856
1857                wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + mWallpaperAnimLayerAdjustment;
1858                if (DEBUG_LAYERS || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "adjustWallpaper win "
1859                        + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer);
1860
1861                // First, if this window is at the current index, then all
1862                // is well.
1863                if (wallpaper == foundW) {
1864                    foundI--;
1865                    foundW = foundI > 0
1866                            ? windows.get(foundI-1) : null;
1867                    continue;
1868                }
1869
1870                // The window didn't match...  the current wallpaper window,
1871                // wherever it is, is in the wrong place, so make sure it is
1872                // not in the list.
1873                int oldIndex = windows.indexOf(wallpaper);
1874                if (oldIndex >= 0) {
1875                    if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Wallpaper removing at "
1876                            + oldIndex + ": " + wallpaper);
1877                    windows.remove(oldIndex);
1878                    mWindowsChanged = true;
1879                    if (oldIndex < foundI) {
1880                        foundI--;
1881                    }
1882                }
1883
1884                // Now stick it in. For apps over wallpaper keep the wallpaper at the bottommost
1885                // layer. For keyguard over wallpaper put the wallpaper under the keyguard.
1886                int insertionIndex = 0;
1887                if (visible && foundW != null) {
1888                    final int type = foundW.mAttrs.type;
1889                    if (type == TYPE_KEYGUARD || type == TYPE_KEYGUARD_SCRIM) {
1890                        insertionIndex = windows.indexOf(foundW);
1891                    }
1892                }
1893                if (DEBUG_WALLPAPER_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) {
1894                    Slog.v(TAG, "Moving wallpaper " + wallpaper
1895                            + " from " + oldIndex + " to " + insertionIndex);
1896                }
1897
1898                windows.add(insertionIndex, wallpaper);
1899                mWindowsChanged = true;
1900                changed |= ADJUST_WALLPAPER_LAYERS_CHANGED;
1901            }
1902        }
1903
1904        /*
1905        final TaskStack targetStack =
1906                mWallpaperTarget == null ? null : mWallpaperTarget.getStack();
1907        if ((changed & ADJUST_WALLPAPER_LAYERS_CHANGED) != 0 &&
1908                targetStack != null && !targetStack.isHomeStack()) {
1909            // If the wallpaper target is not on the home stack then make sure that all windows
1910            // from other non-home stacks are above the wallpaper.
1911            for (i = foundI - 1; i >= 0; --i) {
1912                WindowState win = windows.get(i);
1913                if (!win.isVisibleLw()) {
1914                    continue;
1915                }
1916                final TaskStack winStack = win.getStack();
1917                if (winStack != null && !winStack.isHomeStack() && winStack != targetStack) {
1918                    windows.remove(i);
1919                    windows.add(foundI + 1, win);
1920                }
1921            }
1922        }
1923        */
1924
1925        if (targetChanged && DEBUG_WALLPAPER_LIGHT) {
1926            Slog.d(TAG, "New wallpaper: target=" + mWallpaperTarget
1927                    + " lower=" + mLowerWallpaperTarget + " upper="
1928                    + mUpperWallpaperTarget);
1929        }
1930
1931        return changed;
1932    }
1933
1934    void setWallpaperAnimLayerAdjustmentLocked(int adj) {
1935        if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG,
1936                "Setting wallpaper layer adj to " + adj);
1937        mWallpaperAnimLayerAdjustment = adj;
1938        int curTokenIndex = mWallpaperTokens.size();
1939        while (curTokenIndex > 0) {
1940            curTokenIndex--;
1941            WindowToken token = mWallpaperTokens.get(curTokenIndex);
1942            int curWallpaperIndex = token.windows.size();
1943            while (curWallpaperIndex > 0) {
1944                curWallpaperIndex--;
1945                WindowState wallpaper = token.windows.get(curWallpaperIndex);
1946                wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + adj;
1947                if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "setWallpaper win "
1948                        + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer);
1949            }
1950        }
1951    }
1952
1953    boolean updateWallpaperOffsetLocked(WindowState wallpaperWin, int dw, int dh,
1954            boolean sync) {
1955        boolean changed = false;
1956        boolean rawChanged = false;
1957        float wpx = mLastWallpaperX >= 0 ? mLastWallpaperX : 0.5f;
1958        float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f;
1959        int availw = wallpaperWin.mFrame.right-wallpaperWin.mFrame.left-dw;
1960        int offset = availw > 0 ? -(int)(availw*wpx+.5f) : 0;
1961        changed = wallpaperWin.mXOffset != offset;
1962        if (changed) {
1963            if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper "
1964                    + wallpaperWin + " x: " + offset);
1965            wallpaperWin.mXOffset = offset;
1966        }
1967        if (wallpaperWin.mWallpaperX != wpx || wallpaperWin.mWallpaperXStep != wpxs) {
1968            wallpaperWin.mWallpaperX = wpx;
1969            wallpaperWin.mWallpaperXStep = wpxs;
1970            rawChanged = true;
1971        }
1972
1973        float wpy = mLastWallpaperY >= 0 ? mLastWallpaperY : 0.5f;
1974        float wpys = mLastWallpaperYStep >= 0 ? mLastWallpaperYStep : -1.0f;
1975        int availh = wallpaperWin.mFrame.bottom-wallpaperWin.mFrame.top-dh;
1976        offset = availh > 0 ? -(int)(availh*wpy+.5f) : 0;
1977        if (wallpaperWin.mYOffset != offset) {
1978            if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper "
1979                    + wallpaperWin + " y: " + offset);
1980            changed = true;
1981            wallpaperWin.mYOffset = offset;
1982        }
1983        if (wallpaperWin.mWallpaperY != wpy || wallpaperWin.mWallpaperYStep != wpys) {
1984            wallpaperWin.mWallpaperY = wpy;
1985            wallpaperWin.mWallpaperYStep = wpys;
1986            rawChanged = true;
1987        }
1988
1989        if (rawChanged && (wallpaperWin.mAttrs.privateFlags &
1990                    WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS) != 0) {
1991            try {
1992                if (DEBUG_WALLPAPER) Slog.v(TAG, "Report new wp offset "
1993                        + wallpaperWin + " x=" + wallpaperWin.mWallpaperX
1994                        + " y=" + wallpaperWin.mWallpaperY);
1995                if (sync) {
1996                    mWaitingOnWallpaper = wallpaperWin;
1997                }
1998                wallpaperWin.mClient.dispatchWallpaperOffsets(
1999                        wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY,
2000                        wallpaperWin.mWallpaperXStep, wallpaperWin.mWallpaperYStep, sync);
2001                if (sync) {
2002                    if (mWaitingOnWallpaper != null) {
2003                        long start = SystemClock.uptimeMillis();
2004                        if ((mLastWallpaperTimeoutTime+WALLPAPER_TIMEOUT_RECOVERY)
2005                                < start) {
2006                            try {
2007                                if (DEBUG_WALLPAPER) Slog.v(TAG,
2008                                        "Waiting for offset complete...");
2009                                mWindowMap.wait(WALLPAPER_TIMEOUT);
2010                            } catch (InterruptedException e) {
2011                            }
2012                            if (DEBUG_WALLPAPER) Slog.v(TAG, "Offset complete!");
2013                            if ((start+WALLPAPER_TIMEOUT)
2014                                    < SystemClock.uptimeMillis()) {
2015                                Slog.i(TAG, "Timeout waiting for wallpaper to offset: "
2016                                        + wallpaperWin);
2017                                mLastWallpaperTimeoutTime = start;
2018                            }
2019                        }
2020                        mWaitingOnWallpaper = null;
2021                    }
2022                }
2023            } catch (RemoteException e) {
2024            }
2025        }
2026
2027        return changed;
2028    }
2029
2030    void wallpaperOffsetsComplete(IBinder window) {
2031        synchronized (mWindowMap) {
2032            if (mWaitingOnWallpaper != null &&
2033                    mWaitingOnWallpaper.mClient.asBinder() == window) {
2034                mWaitingOnWallpaper = null;
2035                mWindowMap.notifyAll();
2036            }
2037        }
2038    }
2039
2040    void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
2041        final DisplayContent displayContent = changingTarget.getDisplayContent();
2042        if (displayContent == null) {
2043            return;
2044        }
2045        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2046        final int dw = displayInfo.logicalWidth;
2047        final int dh = displayInfo.logicalHeight;
2048
2049        WindowState target = mWallpaperTarget;
2050        if (target != null) {
2051            if (target.mWallpaperX >= 0) {
2052                mLastWallpaperX = target.mWallpaperX;
2053            } else if (changingTarget.mWallpaperX >= 0) {
2054                mLastWallpaperX = changingTarget.mWallpaperX;
2055            }
2056            if (target.mWallpaperY >= 0) {
2057                mLastWallpaperY = target.mWallpaperY;
2058            } else if (changingTarget.mWallpaperY >= 0) {
2059                mLastWallpaperY = changingTarget.mWallpaperY;
2060            }
2061        }
2062
2063        int curTokenIndex = mWallpaperTokens.size();
2064        while (curTokenIndex > 0) {
2065            curTokenIndex--;
2066            WindowToken token = mWallpaperTokens.get(curTokenIndex);
2067            int curWallpaperIndex = token.windows.size();
2068            while (curWallpaperIndex > 0) {
2069                curWallpaperIndex--;
2070                WindowState wallpaper = token.windows.get(curWallpaperIndex);
2071                if (updateWallpaperOffsetLocked(wallpaper, dw, dh, sync)) {
2072                    WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
2073                    winAnimator.computeShownFrameLocked();
2074                    // No need to lay out the windows - we can just set the wallpaper position
2075                    // directly.
2076                    winAnimator.setWallpaperOffset(wallpaper.mShownFrame);
2077                    // We only want to be synchronous with one wallpaper.
2078                    sync = false;
2079                }
2080            }
2081        }
2082    }
2083
2084    /**
2085     * Check wallpaper for visiblity change and notify window if so.
2086     * @param wallpaper The wallpaper to test and notify.
2087     * @param visible Current visibility.
2088     */
2089    void dispatchWallpaperVisibility(final WindowState wallpaper, final boolean visible) {
2090        if (wallpaper.mWallpaperVisible != visible) {
2091            wallpaper.mWallpaperVisible = visible;
2092            try {
2093                if (DEBUG_VISIBILITY || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
2094                        "Updating vis of wallpaper " + wallpaper
2095                        + ": " + visible + " from:\n" + Debug.getCallers(4, "  "));
2096                wallpaper.mClient.dispatchAppVisibility(visible);
2097            } catch (RemoteException e) {
2098            }
2099        }
2100    }
2101
2102    void updateWallpaperVisibilityLocked() {
2103        final boolean visible = isWallpaperVisible(mWallpaperTarget);
2104        final DisplayContent displayContent = mWallpaperTarget.getDisplayContent();
2105        if (displayContent == null) {
2106            return;
2107        }
2108        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2109        final int dw = displayInfo.logicalWidth;
2110        final int dh = displayInfo.logicalHeight;
2111
2112        int curTokenIndex = mWallpaperTokens.size();
2113        while (curTokenIndex > 0) {
2114            curTokenIndex--;
2115            WindowToken token = mWallpaperTokens.get(curTokenIndex);
2116            if (token.hidden == visible) {
2117                token.hidden = !visible;
2118                // Need to do a layout to ensure the wallpaper now has the
2119                // correct size.
2120                getDefaultDisplayContentLocked().layoutNeeded = true;
2121            }
2122
2123            int curWallpaperIndex = token.windows.size();
2124            while (curWallpaperIndex > 0) {
2125                curWallpaperIndex--;
2126                WindowState wallpaper = token.windows.get(curWallpaperIndex);
2127                if (visible) {
2128                    updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
2129                }
2130
2131                dispatchWallpaperVisibility(wallpaper, visible);
2132            }
2133        }
2134    }
2135
2136    public int addWindow(Session session, IWindow client, int seq,
2137            WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
2138            Rect outContentInsets, InputChannel outInputChannel) {
2139        int[] appOp = new int[1];
2140        int res = mPolicy.checkAddPermission(attrs, appOp);
2141        if (res != WindowManagerGlobal.ADD_OKAY) {
2142            return res;
2143        }
2144
2145        boolean reportNewConfig = false;
2146        WindowState attachedWindow = null;
2147        WindowState win = null;
2148        long origId;
2149        final int type = attrs.type;
2150
2151        synchronized(mWindowMap) {
2152            if (!mDisplayReady) {
2153                throw new IllegalStateException("Display has not been initialialized");
2154            }
2155
2156            final DisplayContent displayContent = getDisplayContentLocked(displayId);
2157            if (displayContent == null) {
2158                Slog.w(TAG, "Attempted to add window to a display that does not exist: "
2159                        + displayId + ".  Aborting.");
2160                return WindowManagerGlobal.ADD_INVALID_DISPLAY;
2161            }
2162            if (!displayContent.hasAccess(session.mUid)) {
2163                Slog.w(TAG, "Attempted to add window to a display for which the application "
2164                        + "does not have access: " + displayId + ".  Aborting.");
2165                return WindowManagerGlobal.ADD_INVALID_DISPLAY;
2166            }
2167
2168            if (mWindowMap.containsKey(client.asBinder())) {
2169                Slog.w(TAG, "Window " + client + " is already added");
2170                return WindowManagerGlobal.ADD_DUPLICATE_ADD;
2171            }
2172
2173            if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) {
2174                attachedWindow = windowForClientLocked(null, attrs.token, false);
2175                if (attachedWindow == null) {
2176                    Slog.w(TAG, "Attempted to add window with token that is not a window: "
2177                          + attrs.token + ".  Aborting.");
2178                    return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
2179                }
2180                if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW
2181                        && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) {
2182                    Slog.w(TAG, "Attempted to add window with token that is a sub-window: "
2183                            + attrs.token + ".  Aborting.");
2184                    return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
2185                }
2186            }
2187
2188            if (type == TYPE_PRIVATE_PRESENTATION && !displayContent.isPrivate()) {
2189                Slog.w(TAG, "Attempted to add private presentation window to a non-private display.  Aborting.");
2190                return WindowManagerGlobal.ADD_PERMISSION_DENIED;
2191            }
2192
2193            boolean addToken = false;
2194            WindowToken token = mTokenMap.get(attrs.token);
2195            if (token == null) {
2196                if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
2197                    Slog.w(TAG, "Attempted to add application window with unknown token "
2198                          + attrs.token + ".  Aborting.");
2199                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2200                }
2201                if (type == TYPE_INPUT_METHOD) {
2202                    Slog.w(TAG, "Attempted to add input method window with unknown token "
2203                          + attrs.token + ".  Aborting.");
2204                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2205                }
2206                if (type == TYPE_WALLPAPER) {
2207                    Slog.w(TAG, "Attempted to add wallpaper window with unknown token "
2208                          + attrs.token + ".  Aborting.");
2209                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2210                }
2211                if (type == TYPE_DREAM) {
2212                    Slog.w(TAG, "Attempted to add Dream window with unknown token "
2213                          + attrs.token + ".  Aborting.");
2214                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2215                }
2216                token = new WindowToken(this, attrs.token, -1, false);
2217                addToken = true;
2218            } else if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
2219                AppWindowToken atoken = token.appWindowToken;
2220                if (atoken == null) {
2221                    Slog.w(TAG, "Attempted to add window with non-application token "
2222                          + token + ".  Aborting.");
2223                    return WindowManagerGlobal.ADD_NOT_APP_TOKEN;
2224                } else if (atoken.removed) {
2225                    Slog.w(TAG, "Attempted to add window with exiting application token "
2226                          + token + ".  Aborting.");
2227                    return WindowManagerGlobal.ADD_APP_EXITING;
2228                }
2229                if (type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) {
2230                    // No need for this guy!
2231                    if (localLOGV) Slog.v(
2232                            TAG, "**** NO NEED TO START: " + attrs.getTitle());
2233                    return WindowManagerGlobal.ADD_STARTING_NOT_NEEDED;
2234                }
2235            } else if (type == TYPE_INPUT_METHOD) {
2236                if (token.windowType != TYPE_INPUT_METHOD) {
2237                    Slog.w(TAG, "Attempted to add input method window with bad token "
2238                            + attrs.token + ".  Aborting.");
2239                      return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2240                }
2241            } else if (type == TYPE_WALLPAPER) {
2242                if (token.windowType != TYPE_WALLPAPER) {
2243                    Slog.w(TAG, "Attempted to add wallpaper window with bad token "
2244                            + attrs.token + ".  Aborting.");
2245                      return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2246                }
2247            } else if (type == TYPE_DREAM) {
2248                if (token.windowType != TYPE_DREAM) {
2249                    Slog.w(TAG, "Attempted to add Dream window with bad token "
2250                            + attrs.token + ".  Aborting.");
2251                      return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2252                }
2253            }
2254
2255            win = new WindowState(this, session, client, token,
2256                    attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
2257            if (win.mDeathRecipient == null) {
2258                // Client has apparently died, so there is no reason to
2259                // continue.
2260                Slog.w(TAG, "Adding window client " + client.asBinder()
2261                        + " that is dead, aborting.");
2262                return WindowManagerGlobal.ADD_APP_EXITING;
2263            }
2264
2265            if (win.getDisplayContent() == null) {
2266                Slog.w(TAG, "Adding window to Display that has been removed.");
2267                return WindowManagerGlobal.ADD_INVALID_DISPLAY;
2268            }
2269
2270            mPolicy.adjustWindowParamsLw(win.mAttrs);
2271            win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs));
2272
2273            res = mPolicy.prepareAddWindowLw(win, attrs);
2274            if (res != WindowManagerGlobal.ADD_OKAY) {
2275                return res;
2276            }
2277
2278            if (outInputChannel != null && (attrs.inputFeatures
2279                    & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
2280                String name = win.makeInputChannelName();
2281                InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
2282                win.setInputChannel(inputChannels[0]);
2283                inputChannels[1].transferTo(outInputChannel);
2284
2285                mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);
2286            }
2287
2288            // From now on, no exceptions or errors allowed!
2289
2290            res = WindowManagerGlobal.ADD_OKAY;
2291
2292            origId = Binder.clearCallingIdentity();
2293
2294            if (addToken) {
2295                mTokenMap.put(attrs.token, token);
2296            }
2297            win.attach();
2298            mWindowMap.put(client.asBinder(), win);
2299            if (win.mAppOp != AppOpsManager.OP_NONE) {
2300                if (mAppOps.startOpNoThrow(win.mAppOp, win.getOwningUid(), win.getOwningPackage())
2301                        != AppOpsManager.MODE_ALLOWED) {
2302                    win.setAppOpVisibilityLw(false);
2303                }
2304            }
2305
2306            if (type == TYPE_APPLICATION_STARTING && token.appWindowToken != null) {
2307                token.appWindowToken.startingWindow = win;
2308                if (DEBUG_STARTING_WINDOW) Slog.v (TAG, "addWindow: " + token.appWindowToken
2309                        + " startingWindow=" + win);
2310                Message m = mH.obtainMessage(H.REMOVE_STARTING_TIMEOUT, token.appWindowToken);
2311                mH.sendMessageDelayed(m, STARTING_WINDOW_TIMEOUT_DURATION);
2312            }
2313
2314            boolean imMayMove = true;
2315
2316            if (type == TYPE_INPUT_METHOD) {
2317                win.mGivenInsetsPending = true;
2318                mInputMethodWindow = win;
2319                addInputMethodWindowToListLocked(win);
2320                imMayMove = false;
2321            } else if (type == TYPE_INPUT_METHOD_DIALOG) {
2322                mInputMethodDialogs.add(win);
2323                addWindowToListInOrderLocked(win, true);
2324                moveInputMethodDialogsLocked(findDesiredInputMethodWindowIndexLocked(true));
2325                imMayMove = false;
2326            } else {
2327                addWindowToListInOrderLocked(win, true);
2328                if (type == TYPE_WALLPAPER) {
2329                    mLastWallpaperTimeoutTime = 0;
2330                    displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2331                } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
2332                    displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2333                } else if (mWallpaperTarget != null
2334                        && mWallpaperTarget.mLayer >= win.mBaseLayer) {
2335                    // If there is currently a wallpaper being shown, and
2336                    // the base layer of the new window is below the current
2337                    // layer of the target window, then adjust the wallpaper.
2338                    // This is to avoid a new window being placed between the
2339                    // wallpaper and its target.
2340                    displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2341                }
2342            }
2343
2344            win.mWinAnimator.mEnterAnimationPending = true;
2345
2346            if (displayContent.isDefaultDisplay) {
2347                mPolicy.getContentInsetHintLw(attrs, outContentInsets);
2348            } else {
2349                outContentInsets.setEmpty();
2350            }
2351
2352            if (mInTouchMode) {
2353                res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
2354            }
2355            if (win.mAppToken == null || !win.mAppToken.clientHidden) {
2356                res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE;
2357            }
2358
2359            mInputMonitor.setUpdateInputWindowsNeededLw();
2360
2361            boolean focusChanged = false;
2362            if (win.canReceiveKeys()) {
2363                focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
2364                        false /*updateInputWindows*/);
2365                if (focusChanged) {
2366                    imMayMove = false;
2367                }
2368            }
2369
2370            if (imMayMove) {
2371                moveInputMethodWindowsIfNeededLocked(false);
2372            }
2373
2374            assignLayersLocked(displayContent.getWindowList());
2375            // Don't do layout here, the window must call
2376            // relayout to be displayed, so we'll do it there.
2377
2378            if (focusChanged) {
2379                finishUpdateFocusedWindowAfterAssignLayersLocked(false /*updateInputWindows*/);
2380            }
2381            mInputMonitor.updateInputWindowsLw(false /*force*/);
2382
2383            if (localLOGV) Slog.v(
2384                TAG, "New client " + client.asBinder()
2385                + ": window=" + win);
2386
2387            if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) {
2388                reportNewConfig = true;
2389            }
2390        }
2391
2392        if (reportNewConfig) {
2393            sendNewConfiguration();
2394        }
2395
2396        Binder.restoreCallingIdentity(origId);
2397
2398        return res;
2399    }
2400
2401    public void removeWindow(Session session, IWindow client) {
2402        synchronized(mWindowMap) {
2403            WindowState win = windowForClientLocked(session, client, false);
2404            if (win == null) {
2405                return;
2406            }
2407            removeWindowLocked(session, win);
2408        }
2409    }
2410
2411    public void removeWindowLocked(Session session, WindowState win) {
2412        if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
2413            if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "Starting window removed " + win);
2414            removeStartingWindowTimeout(win.mAppToken);
2415        }
2416
2417        if (localLOGV || DEBUG_FOCUS || DEBUG_FOCUS_LIGHT && win==mCurrentFocus) Slog.v(
2418                TAG, "Remove " + win + " client="
2419                + Integer.toHexString(System.identityHashCode(win.mClient.asBinder()))
2420                + ", surface=" + win.mWinAnimator.mSurfaceControl + " Callers="
2421                + Debug.getCallers(4));
2422
2423        final long origId = Binder.clearCallingIdentity();
2424
2425        win.disposeInputChannel();
2426
2427        if (DEBUG_APP_TRANSITIONS) Slog.v(
2428                TAG, "Remove " + win + ": mSurface=" + win.mWinAnimator.mSurfaceControl
2429                + " mExiting=" + win.mExiting
2430                + " isAnimating=" + win.mWinAnimator.isAnimating()
2431                + " app-animation="
2432                + (win.mAppToken != null ? win.mAppToken.mAppAnimator.animation : null)
2433                + " inPendingTransaction="
2434                + (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false)
2435                + " mDisplayFrozen=" + mDisplayFrozen);
2436        // Visibility of the removed window. Will be used later to update orientation later on.
2437        boolean wasVisible = false;
2438        // First, see if we need to run an animation.  If we do, we have
2439        // to hold off on removing the window until the animation is done.
2440        // If the display is frozen, just remove immediately, since the
2441        // animation wouldn't be seen.
2442        if (win.mHasSurface && okToDisplay()) {
2443            // If we are not currently running the exit animation, we
2444            // need to see about starting one.
2445            wasVisible = win.isWinVisibleLw();
2446            if (wasVisible) {
2447
2448                int transit = WindowManagerPolicy.TRANSIT_EXIT;
2449                if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
2450                    transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
2451                }
2452                // Try starting an animation.
2453                if (win.mWinAnimator.applyAnimationLocked(transit, false)) {
2454                    win.mExiting = true;
2455                }
2456                //TODO (multidisplay): Magnification is supported only for the default display.
2457                if (mDisplayMagnifier != null
2458                        && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
2459                    mDisplayMagnifier.onWindowTransitionLocked(win, transit);
2460                }
2461            }
2462            if (win.mExiting || win.mWinAnimator.isAnimating()) {
2463                // The exit animation is running... wait for it!
2464                //Slog.i(TAG, "*** Running exit animation...");
2465                win.mExiting = true;
2466                win.mRemoveOnExit = true;
2467                final DisplayContent displayContent = win.getDisplayContent();
2468                if (displayContent != null) {
2469                    displayContent.layoutNeeded = true;
2470                }
2471                updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
2472                        false /*updateInputWindows*/);
2473                performLayoutAndPlaceSurfacesLocked();
2474                if (win.mAppToken != null) {
2475                    win.mAppToken.updateReportedVisibilityLocked();
2476                }
2477                //dump();
2478                Binder.restoreCallingIdentity(origId);
2479                return;
2480            }
2481        }
2482
2483        removeWindowInnerLocked(session, win);
2484        // Removing a visible window will effect the computed orientation
2485        // So just update orientation if needed.
2486        if (wasVisible && updateOrientationFromAppTokensLocked(false)) {
2487            mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
2488        }
2489        updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
2490        Binder.restoreCallingIdentity(origId);
2491    }
2492
2493    private void removeWindowInnerLocked(Session session, WindowState win) {
2494        if (win.mRemoved) {
2495            // Nothing to do.
2496            return;
2497        }
2498
2499        for (int i=win.mChildWindows.size()-1; i>=0; i--) {
2500            WindowState cwin = win.mChildWindows.get(i);
2501            Slog.w(TAG, "Force-removing child win " + cwin + " from container "
2502                    + win);
2503            removeWindowInnerLocked(cwin.mSession, cwin);
2504        }
2505
2506        win.mRemoved = true;
2507
2508        if (mInputMethodTarget == win) {
2509            moveInputMethodWindowsIfNeededLocked(false);
2510        }
2511
2512        if (false) {
2513            RuntimeException e = new RuntimeException("here");
2514            e.fillInStackTrace();
2515            Slog.w(TAG, "Removing window " + win, e);
2516        }
2517
2518        mPolicy.removeWindowLw(win);
2519        win.removeLocked();
2520
2521        if (DEBUG_ADD_REMOVE) Slog.v(TAG, "removeWindowInnerLocked: " + win);
2522        mWindowMap.remove(win.mClient.asBinder());
2523        if (win.mAppOp != AppOpsManager.OP_NONE) {
2524            mAppOps.finishOp(win.mAppOp, win.getOwningUid(), win.getOwningPackage());
2525        }
2526
2527        mPendingRemove.remove(win);
2528        mResizingWindows.remove(win);
2529        mWindowsChanged = true;
2530        if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Final remove of window: " + win);
2531
2532        if (mInputMethodWindow == win) {
2533            mInputMethodWindow = null;
2534        } else if (win.mAttrs.type == TYPE_INPUT_METHOD_DIALOG) {
2535            mInputMethodDialogs.remove(win);
2536        }
2537
2538        final WindowToken token = win.mToken;
2539        final AppWindowToken atoken = win.mAppToken;
2540        if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing " + win + " from " + token);
2541        token.windows.remove(win);
2542        if (atoken != null) {
2543            atoken.allAppWindows.remove(win);
2544        }
2545        if (localLOGV) Slog.v(
2546                TAG, "**** Removing window " + win + ": count="
2547                + token.windows.size());
2548        if (token.windows.size() == 0) {
2549            if (!token.explicit) {
2550                mTokenMap.remove(token.token);
2551            } else if (atoken != null) {
2552                atoken.firstWindowDrawn = false;
2553            }
2554        }
2555
2556        if (atoken != null) {
2557            if (atoken.startingWindow == win) {
2558                if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Nulling startingWindow " + win);
2559                removeStartingWindowTimeout(atoken);
2560                atoken.startingWindow = null;
2561            } else if (atoken.allAppWindows.size() == 0 && atoken.startingData != null) {
2562                // If this is the last window and we had requested a starting
2563                // transition window, well there is no point now.
2564                if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Nulling last startingWindow");
2565                atoken.startingData = null;
2566            } else if (atoken.allAppWindows.size() == 1 && atoken.startingView != null) {
2567                // If this is the last window except for a starting transition
2568                // window, we need to get rid of the starting transition.
2569                scheduleRemoveStartingWindow(atoken);
2570            }
2571        }
2572
2573        if (win.mAttrs.type == TYPE_WALLPAPER) {
2574            mLastWallpaperTimeoutTime = 0;
2575            getDefaultDisplayContentLocked().pendingLayoutChanges |=
2576                    WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
2577        } else if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
2578            getDefaultDisplayContentLocked().pendingLayoutChanges |=
2579                    WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
2580        }
2581
2582        final WindowList windows = win.getWindowList();
2583        if (windows != null) {
2584            windows.remove(win);
2585            if (!mInLayout) {
2586                assignLayersLocked(windows);
2587                final DisplayContent displayContent = win.getDisplayContent();
2588                if (displayContent != null) {
2589                    displayContent.layoutNeeded = true;
2590                }
2591                performLayoutAndPlaceSurfacesLocked();
2592                if (win.mAppToken != null) {
2593                    win.mAppToken.updateReportedVisibilityLocked();
2594                }
2595            }
2596        }
2597
2598        mInputMonitor.updateInputWindowsLw(true /*force*/);
2599    }
2600
2601    public void updateAppOpsState() {
2602        synchronized(mWindowMap) {
2603            final int numDisplays = mDisplayContents.size();
2604            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
2605                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
2606                final int numWindows = windows.size();
2607                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
2608                    final WindowState win = windows.get(winNdx);
2609                    if (win.mAppOp != AppOpsManager.OP_NONE) {
2610                        final int mode = mAppOps.checkOpNoThrow(win.mAppOp, win.getOwningUid(),
2611                                win.getOwningPackage());
2612                        win.setAppOpVisibilityLw(mode == AppOpsManager.MODE_ALLOWED);
2613                    }
2614                }
2615            }
2616        }
2617    }
2618
2619    static void logSurface(WindowState w, String msg, RuntimeException where) {
2620        String str = "  SURFACE " + msg + ": " + w;
2621        if (where != null) {
2622            Slog.i(TAG, str, where);
2623        } else {
2624            Slog.i(TAG, str);
2625        }
2626    }
2627
2628    static void logSurface(SurfaceControl s, String title, String msg, RuntimeException where) {
2629        String str = "  SURFACE " + s + ": " + msg + " / " + title;
2630        if (where != null) {
2631            Slog.i(TAG, str, where);
2632        } else {
2633            Slog.i(TAG, str);
2634        }
2635    }
2636
2637    void setTransparentRegionWindow(Session session, IWindow client, Region region) {
2638        long origId = Binder.clearCallingIdentity();
2639        try {
2640            synchronized (mWindowMap) {
2641                WindowState w = windowForClientLocked(session, client, false);
2642                if ((w != null) && w.mHasSurface) {
2643                    w.mWinAnimator.setTransparentRegionHintLocked(region);
2644                }
2645            }
2646        } finally {
2647            Binder.restoreCallingIdentity(origId);
2648        }
2649    }
2650
2651    void setInsetsWindow(Session session, IWindow client,
2652            int touchableInsets, Rect contentInsets,
2653            Rect visibleInsets, Region touchableRegion) {
2654        long origId = Binder.clearCallingIdentity();
2655        try {
2656            synchronized (mWindowMap) {
2657                WindowState w = windowForClientLocked(session, client, false);
2658                if (w != null) {
2659                    w.mGivenInsetsPending = false;
2660                    w.mGivenContentInsets.set(contentInsets);
2661                    w.mGivenVisibleInsets.set(visibleInsets);
2662                    w.mGivenTouchableRegion.set(touchableRegion);
2663                    w.mTouchableInsets = touchableInsets;
2664                    if (w.mGlobalScale != 1) {
2665                        w.mGivenContentInsets.scale(w.mGlobalScale);
2666                        w.mGivenVisibleInsets.scale(w.mGlobalScale);
2667                        w.mGivenTouchableRegion.scale(w.mGlobalScale);
2668                    }
2669                    final DisplayContent displayContent = w.getDisplayContent();
2670                    if (displayContent != null) {
2671                        displayContent.layoutNeeded = true;
2672                    }
2673                    performLayoutAndPlaceSurfacesLocked();
2674                }
2675            }
2676        } finally {
2677            Binder.restoreCallingIdentity(origId);
2678        }
2679    }
2680
2681    public void getWindowDisplayFrame(Session session, IWindow client,
2682            Rect outDisplayFrame) {
2683        synchronized(mWindowMap) {
2684            WindowState win = windowForClientLocked(session, client, false);
2685            if (win == null) {
2686                outDisplayFrame.setEmpty();
2687                return;
2688            }
2689            outDisplayFrame.set(win.mDisplayFrame);
2690        }
2691    }
2692
2693    public void setWindowWallpaperPositionLocked(WindowState window, float x, float y,
2694            float xStep, float yStep) {
2695        if (window.mWallpaperX != x || window.mWallpaperY != y)  {
2696            window.mWallpaperX = x;
2697            window.mWallpaperY = y;
2698            window.mWallpaperXStep = xStep;
2699            window.mWallpaperYStep = yStep;
2700            updateWallpaperOffsetLocked(window, true);
2701        }
2702    }
2703
2704    void wallpaperCommandComplete(IBinder window, Bundle result) {
2705        synchronized (mWindowMap) {
2706            if (mWaitingOnWallpaper != null &&
2707                    mWaitingOnWallpaper.mClient.asBinder() == window) {
2708                mWaitingOnWallpaper = null;
2709                mWindowMap.notifyAll();
2710            }
2711        }
2712    }
2713
2714    public Bundle sendWindowWallpaperCommandLocked(WindowState window,
2715            String action, int x, int y, int z, Bundle extras, boolean sync) {
2716        if (window == mWallpaperTarget || window == mLowerWallpaperTarget
2717                || window == mUpperWallpaperTarget) {
2718            boolean doWait = sync;
2719            int curTokenIndex = mWallpaperTokens.size();
2720            while (curTokenIndex > 0) {
2721                curTokenIndex--;
2722                WindowToken token = mWallpaperTokens.get(curTokenIndex);
2723                int curWallpaperIndex = token.windows.size();
2724                while (curWallpaperIndex > 0) {
2725                    curWallpaperIndex--;
2726                    WindowState wallpaper = token.windows.get(curWallpaperIndex);
2727                    try {
2728                        wallpaper.mClient.dispatchWallpaperCommand(action,
2729                                x, y, z, extras, sync);
2730                        // We only want to be synchronous with one wallpaper.
2731                        sync = false;
2732                    } catch (RemoteException e) {
2733                    }
2734                }
2735            }
2736
2737            if (doWait) {
2738                // XXX Need to wait for result.
2739            }
2740        }
2741
2742        return null;
2743    }
2744
2745    public void setUniverseTransformLocked(WindowState window, float alpha,
2746            float offx, float offy, float dsdx, float dtdx, float dsdy, float dtdy) {
2747        Transformation transform = window.mWinAnimator.mUniverseTransform;
2748        transform.setAlpha(alpha);
2749        Matrix matrix = transform.getMatrix();
2750        matrix.getValues(mTmpFloats);
2751        mTmpFloats[Matrix.MTRANS_X] = offx;
2752        mTmpFloats[Matrix.MTRANS_Y] = offy;
2753        mTmpFloats[Matrix.MSCALE_X] = dsdx;
2754        mTmpFloats[Matrix.MSKEW_Y] = dtdx;
2755        mTmpFloats[Matrix.MSKEW_X] = dsdy;
2756        mTmpFloats[Matrix.MSCALE_Y] = dtdy;
2757        matrix.setValues(mTmpFloats);
2758        final DisplayContent displayContent = window.getDisplayContent();
2759        if (displayContent == null) {
2760            return;
2761        }
2762
2763        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2764        final RectF dispRect = new RectF(0, 0,
2765                displayInfo.logicalWidth, displayInfo.logicalHeight);
2766        matrix.mapRect(dispRect);
2767        window.mGivenTouchableRegion.set(0, 0,
2768                displayInfo.logicalWidth, displayInfo.logicalHeight);
2769        window.mGivenTouchableRegion.op((int)dispRect.left, (int)dispRect.top,
2770                (int)dispRect.right, (int)dispRect.bottom, Region.Op.DIFFERENCE);
2771        window.mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
2772        displayContent.layoutNeeded = true;
2773        performLayoutAndPlaceSurfacesLocked();
2774    }
2775
2776    public void onRectangleOnScreenRequested(IBinder token, Rect rectangle, boolean immediate) {
2777        synchronized (mWindowMap) {
2778            if (mDisplayMagnifier != null) {
2779                WindowState window = mWindowMap.get(token);
2780                //TODO (multidisplay): Magnification is supported only for the default display.
2781                if (window != null && window.getDisplayId() == Display.DEFAULT_DISPLAY) {
2782                    mDisplayMagnifier.onRectangleOnScreenRequestedLocked(rectangle, immediate);
2783                }
2784            }
2785        }
2786    }
2787
2788    public IWindowId getWindowId(IBinder token) {
2789        synchronized (mWindowMap) {
2790            WindowState window = mWindowMap.get(token);
2791            return window != null ? window.mWindowId : null;
2792        }
2793    }
2794
2795    public int relayoutWindow(Session session, IWindow client, int seq,
2796            WindowManager.LayoutParams attrs, int requestedWidth,
2797            int requestedHeight, int viewVisibility, int flags,
2798            Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
2799            Rect outVisibleInsets, Configuration outConfig, Surface outSurface) {
2800        boolean toBeDisplayed = false;
2801        boolean inTouchMode;
2802        boolean configChanged;
2803        boolean surfaceChanged = false;
2804        boolean animating;
2805
2806        // if they don't have this permission, mask out the status bar bits
2807        int systemUiVisibility = 0;
2808        if (attrs != null) {
2809            systemUiVisibility = (attrs.systemUiVisibility|attrs.subtreeSystemUiVisibility);
2810            if ((systemUiVisibility & StatusBarManager.DISABLE_MASK) != 0) {
2811                if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
2812                        != PackageManager.PERMISSION_GRANTED) {
2813                    systemUiVisibility &= ~StatusBarManager.DISABLE_MASK;
2814                }
2815            }
2816        }
2817        long origId = Binder.clearCallingIdentity();
2818
2819        synchronized(mWindowMap) {
2820            WindowState win = windowForClientLocked(session, client, false);
2821            if (win == null) {
2822                return 0;
2823            }
2824            WindowStateAnimator winAnimator = win.mWinAnimator;
2825            if (win.mRequestedWidth != requestedWidth
2826                    || win.mRequestedHeight != requestedHeight) {
2827                win.mLayoutNeeded = true;
2828                win.mRequestedWidth = requestedWidth;
2829                win.mRequestedHeight = requestedHeight;
2830            }
2831            if (attrs != null && seq == win.mSeq) {
2832                win.mSystemUiVisibility = systemUiVisibility;
2833            }
2834
2835            if (attrs != null) {
2836                mPolicy.adjustWindowParamsLw(attrs);
2837            }
2838
2839            winAnimator.mSurfaceDestroyDeferred =
2840                    (flags&WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY) != 0;
2841
2842            int attrChanges = 0;
2843            int flagChanges = 0;
2844            if (attrs != null) {
2845                if (win.mAttrs.type != attrs.type) {
2846                    throw new IllegalArgumentException(
2847                            "Window type can not be changed after the window is added.");
2848                }
2849                flagChanges = win.mAttrs.flags ^= attrs.flags;
2850                attrChanges = win.mAttrs.copyFrom(attrs);
2851                if ((attrChanges & (WindowManager.LayoutParams.LAYOUT_CHANGED
2852                        | WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED)) != 0) {
2853                    win.mLayoutNeeded = true;
2854                }
2855            }
2856
2857            if (DEBUG_LAYOUT) Slog.v(TAG, "Relayout " + win + ": viewVisibility=" + viewVisibility
2858                    + " req=" + requestedWidth + "x" + requestedHeight + " " + win.mAttrs);
2859
2860            win.mEnforceSizeCompat =
2861                    (win.mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0;
2862
2863            if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) {
2864                winAnimator.mAlpha = attrs.alpha;
2865            }
2866
2867            final boolean scaledWindow =
2868                ((win.mAttrs.flags & WindowManager.LayoutParams.FLAG_SCALED) != 0);
2869
2870            if (scaledWindow) {
2871                // requested{Width|Height} Surface's physical size
2872                // attrs.{width|height} Size on screen
2873                win.mHScale = (attrs.width  != requestedWidth)  ?
2874                        (attrs.width  / (float)requestedWidth) : 1.0f;
2875                win.mVScale = (attrs.height != requestedHeight) ?
2876                        (attrs.height / (float)requestedHeight) : 1.0f;
2877            } else {
2878                win.mHScale = win.mVScale = 1;
2879            }
2880
2881            boolean imMayMove = (flagChanges & (FLAG_ALT_FOCUSABLE_IM | FLAG_NOT_FOCUSABLE)) != 0;
2882
2883            final boolean isDefaultDisplay = win.isDefaultDisplay();
2884            boolean focusMayChange = isDefaultDisplay && (win.mViewVisibility != viewVisibility
2885                    || ((flagChanges & FLAG_NOT_FOCUSABLE) != 0)
2886                    || (!win.mRelayoutCalled));
2887
2888            boolean wallpaperMayMove = win.mViewVisibility != viewVisibility
2889                    && (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
2890            wallpaperMayMove |= (flagChanges & FLAG_SHOW_WALLPAPER) != 0;
2891
2892            win.mRelayoutCalled = true;
2893            final int oldVisibility = win.mViewVisibility;
2894            win.mViewVisibility = viewVisibility;
2895            if (DEBUG_SCREEN_ON) {
2896                RuntimeException stack = new RuntimeException();
2897                stack.fillInStackTrace();
2898                Slog.i(TAG, "Relayout " + win + ": oldVis=" + oldVisibility
2899                        + " newVis=" + viewVisibility, stack);
2900            }
2901            if (viewVisibility == View.VISIBLE &&
2902                    (win.mAppToken == null || !win.mAppToken.clientHidden)) {
2903                toBeDisplayed = !win.isVisibleLw();
2904                if (win.mExiting) {
2905                    winAnimator.cancelExitAnimationForNextAnimationLocked();
2906                    win.mExiting = false;
2907                }
2908                if (win.mDestroying) {
2909                    win.mDestroying = false;
2910                    mDestroySurface.remove(win);
2911                }
2912                if (oldVisibility == View.GONE) {
2913                    winAnimator.mEnterAnimationPending = true;
2914                }
2915                if (toBeDisplayed) {
2916                    if (win.isDrawnLw() && okToDisplay()) {
2917                        winAnimator.applyEnterAnimationLocked();
2918                    }
2919                    if ((win.mAttrs.flags
2920                            & WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) != 0) {
2921                        if (DEBUG_VISIBILITY) Slog.v(TAG,
2922                                "Relayout window turning screen on: " + win);
2923                        win.mTurnOnScreen = true;
2924                    }
2925                    if (win.isConfigChanged()) {
2926                        if (DEBUG_CONFIGURATION) Slog.i(TAG, "Window " + win
2927                                + " visible with new config: " + mCurConfiguration);
2928                        outConfig.setTo(mCurConfiguration);
2929                    }
2930                }
2931                if ((attrChanges&WindowManager.LayoutParams.FORMAT_CHANGED) != 0) {
2932                    // To change the format, we need to re-build the surface.
2933                    winAnimator.destroySurfaceLocked();
2934                    toBeDisplayed = true;
2935                    surfaceChanged = true;
2936                }
2937                try {
2938                    if (!win.mHasSurface) {
2939                        surfaceChanged = true;
2940                    }
2941                    SurfaceControl surfaceControl = winAnimator.createSurfaceLocked();
2942                    if (surfaceControl != null) {
2943                        outSurface.copyFrom(surfaceControl);
2944                        if (SHOW_TRANSACTIONS) Slog.i(TAG,
2945                                "  OUT SURFACE " + outSurface + ": copied");
2946                    } else {
2947                        // For some reason there isn't a surface.  Clear the
2948                        // caller's object so they see the same state.
2949                        outSurface.release();
2950                    }
2951                } catch (Exception e) {
2952                    mInputMonitor.updateInputWindowsLw(true /*force*/);
2953
2954                    Slog.w(TAG, "Exception thrown when creating surface for client "
2955                             + client + " (" + win.mAttrs.getTitle() + ")",
2956                             e);
2957                    Binder.restoreCallingIdentity(origId);
2958                    return 0;
2959                }
2960                if (toBeDisplayed) {
2961                    focusMayChange = isDefaultDisplay;
2962                }
2963                if (win.mAttrs.type == TYPE_INPUT_METHOD
2964                        && mInputMethodWindow == null) {
2965                    mInputMethodWindow = win;
2966                    imMayMove = true;
2967                }
2968                if (win.mAttrs.type == TYPE_BASE_APPLICATION
2969                        && win.mAppToken != null
2970                        && win.mAppToken.startingWindow != null) {
2971                    // Special handling of starting window over the base
2972                    // window of the app: propagate lock screen flags to it,
2973                    // to provide the correct semantics while starting.
2974                    final int mask =
2975                        WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
2976                        | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
2977                        | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
2978                    WindowManager.LayoutParams sa = win.mAppToken.startingWindow.mAttrs;
2979                    sa.flags = (sa.flags&~mask) | (win.mAttrs.flags&mask);
2980                }
2981            } else {
2982                winAnimator.mEnterAnimationPending = false;
2983                if (winAnimator.mSurfaceControl != null) {
2984                    if (DEBUG_VISIBILITY) Slog.i(TAG, "Relayout invis " + win
2985                            + ": mExiting=" + win.mExiting);
2986                    // If we are not currently running the exit animation, we
2987                    // need to see about starting one.
2988                    if (!win.mExiting) {
2989                        surfaceChanged = true;
2990                        // Try starting an animation; if there isn't one, we
2991                        // can destroy the surface right away.
2992                        int transit = WindowManagerPolicy.TRANSIT_EXIT;
2993                        if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
2994                            transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
2995                        }
2996                        if (win.isWinVisibleLw() &&
2997                                winAnimator.applyAnimationLocked(transit, false)) {
2998                            focusMayChange = isDefaultDisplay;
2999                            win.mExiting = true;
3000                        } else if (win.mWinAnimator.isAnimating()) {
3001                            // Currently in a hide animation... turn this into
3002                            // an exit.
3003                            win.mExiting = true;
3004                        } else if (win == mWallpaperTarget) {
3005                            // If the wallpaper is currently behind this
3006                            // window, we need to change both of them inside
3007                            // of a transaction to avoid artifacts.
3008                            win.mExiting = true;
3009                            win.mWinAnimator.mAnimating = true;
3010                        } else {
3011                            if (mInputMethodWindow == win) {
3012                                mInputMethodWindow = null;
3013                            }
3014                            winAnimator.destroySurfaceLocked();
3015                        }
3016                        //TODO (multidisplay): Magnification is supported only for the default
3017                        if (mDisplayMagnifier != null
3018                                && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
3019                            mDisplayMagnifier.onWindowTransitionLocked(win, transit);
3020                        }
3021                    }
3022                }
3023
3024                outSurface.release();
3025                if (DEBUG_VISIBILITY) Slog.i(TAG, "Releasing surface in: " + win);
3026            }
3027
3028            if (focusMayChange) {
3029                //System.out.println("Focus may change: " + win.mAttrs.getTitle());
3030                if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
3031                        false /*updateInputWindows*/)) {
3032                    imMayMove = false;
3033                }
3034                //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus);
3035            }
3036
3037            // updateFocusedWindowLocked() already assigned layers so we only need to
3038            // reassign them at this point if the IM window state gets shuffled
3039            if (imMayMove && (moveInputMethodWindowsIfNeededLocked(false) || toBeDisplayed)) {
3040                // Little hack here -- we -should- be able to rely on the
3041                // function to return true if the IME has moved and needs
3042                // its layer recomputed.  However, if the IME was hidden
3043                // and isn't actually moved in the list, its layer may be
3044                // out of data so we make sure to recompute it.
3045                assignLayersLocked(win.getWindowList());
3046            }
3047
3048            if (wallpaperMayMove) {
3049                getDefaultDisplayContentLocked().pendingLayoutChanges |=
3050                        WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
3051            }
3052
3053            final DisplayContent displayContent = win.getDisplayContent();
3054            if (displayContent != null) {
3055                displayContent.layoutNeeded = true;
3056            }
3057            win.mGivenInsetsPending = (flags&WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0;
3058            configChanged = updateOrientationFromAppTokensLocked(false);
3059            performLayoutAndPlaceSurfacesLocked();
3060            if (toBeDisplayed && win.mIsWallpaper) {
3061                DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
3062                updateWallpaperOffsetLocked(win,
3063                        displayInfo.logicalWidth, displayInfo.logicalHeight, false);
3064            }
3065            if (win.mAppToken != null) {
3066                win.mAppToken.updateReportedVisibilityLocked();
3067            }
3068            outFrame.set(win.mCompatFrame);
3069            outOverscanInsets.set(win.mOverscanInsets);
3070            outContentInsets.set(win.mContentInsets);
3071            outVisibleInsets.set(win.mVisibleInsets);
3072            if (localLOGV) Slog.v(
3073                TAG, "Relayout given client " + client.asBinder()
3074                + ", requestedWidth=" + requestedWidth
3075                + ", requestedHeight=" + requestedHeight
3076                + ", viewVisibility=" + viewVisibility
3077                + "\nRelayout returning frame=" + outFrame
3078                + ", surface=" + outSurface);
3079
3080            if (localLOGV || DEBUG_FOCUS) Slog.v(
3081                TAG, "Relayout of " + win + ": focusMayChange=" + focusMayChange);
3082
3083            inTouchMode = mInTouchMode;
3084            animating = mAnimator.mAnimating && win.mWinAnimator.isAnimating();
3085            if (animating && !mRelayoutWhileAnimating.contains(win)) {
3086                mRelayoutWhileAnimating.add(win);
3087            }
3088
3089            mInputMonitor.updateInputWindowsLw(true /*force*/);
3090
3091            if (DEBUG_LAYOUT) {
3092                Slog.v(TAG, "Relayout complete " + win + ": outFrame=" + outFrame.toShortString());
3093            }
3094        }
3095
3096        if (configChanged) {
3097            sendNewConfiguration();
3098        }
3099
3100        Binder.restoreCallingIdentity(origId);
3101
3102        return (inTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0)
3103                | (toBeDisplayed ? WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME : 0)
3104                | (surfaceChanged ? WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED : 0)
3105                | (animating ? WindowManagerGlobal.RELAYOUT_RES_ANIMATING : 0);
3106    }
3107
3108    public void performDeferredDestroyWindow(Session session, IWindow client) {
3109        long origId = Binder.clearCallingIdentity();
3110
3111        try {
3112            synchronized (mWindowMap) {
3113                WindowState win = windowForClientLocked(session, client, false);
3114                if (win == null) {
3115                    return;
3116                }
3117                win.mWinAnimator.destroyDeferredSurfaceLocked();
3118            }
3119        } finally {
3120            Binder.restoreCallingIdentity(origId);
3121        }
3122    }
3123
3124    public boolean outOfMemoryWindow(Session session, IWindow client) {
3125        long origId = Binder.clearCallingIdentity();
3126
3127        try {
3128            synchronized (mWindowMap) {
3129                WindowState win = windowForClientLocked(session, client, false);
3130                if (win == null) {
3131                    return false;
3132                }
3133                return reclaimSomeSurfaceMemoryLocked(win.mWinAnimator, "from-client", false);
3134            }
3135        } finally {
3136            Binder.restoreCallingIdentity(origId);
3137        }
3138    }
3139
3140    public void finishDrawingWindow(Session session, IWindow client) {
3141        final long origId = Binder.clearCallingIdentity();
3142        try {
3143            synchronized (mWindowMap) {
3144                WindowState win = windowForClientLocked(session, client, false);
3145                if (win != null && win.mWinAnimator.finishDrawingLocked()) {
3146                    if ((win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
3147                        getDefaultDisplayContentLocked().pendingLayoutChanges |=
3148                                WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
3149                    }
3150                    final DisplayContent displayContent = win.getDisplayContent();
3151                    if (displayContent != null) {
3152                        displayContent.layoutNeeded = true;
3153                    }
3154                    requestTraversalLocked();
3155                }
3156            }
3157        } finally {
3158            Binder.restoreCallingIdentity(origId);
3159        }
3160    }
3161
3162    @Override
3163    public void getWindowFrame(IBinder token, Rect outBounds) {
3164        if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO,
3165                "getWindowInfo()")) {
3166            throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission.");
3167        }
3168        synchronized (mWindowMap) {
3169            WindowState windowState = mWindowMap.get(token);
3170            if (windowState != null) {
3171                outBounds.set(windowState.mFrame);
3172            } else {
3173                outBounds.setEmpty();
3174            }
3175        }
3176    }
3177
3178    @Override
3179    public void setMagnificationSpec(MagnificationSpec spec) {
3180        if (!checkCallingPermission(android.Manifest.permission.MAGNIFY_DISPLAY,
3181                "setMagnificationSpec()")) {
3182            throw new SecurityException("Requires MAGNIFY_DISPLAY permission.");
3183        }
3184        synchronized (mWindowMap) {
3185            if (mDisplayMagnifier != null) {
3186                mDisplayMagnifier.setMagnificationSpecLocked(spec);
3187            } else {
3188                throw new IllegalStateException("Magnification callbacks not set!");
3189            }
3190        }
3191        if (Binder.getCallingPid() != android.os.Process.myPid()) {
3192            spec.recycle();
3193        }
3194    }
3195
3196    @Override
3197    public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) {
3198        if (!checkCallingPermission(android.Manifest.permission.MAGNIFY_DISPLAY,
3199                "getCompatibleMagnificationSpecForWindow()")) {
3200            throw new SecurityException("Requires MAGNIFY_DISPLAY permission.");
3201        }
3202        synchronized (mWindowMap) {
3203            WindowState windowState = mWindowMap.get(windowToken);
3204            if (windowState == null) {
3205                return null;
3206            }
3207            MagnificationSpec spec = null;
3208            if (mDisplayMagnifier != null) {
3209                spec = mDisplayMagnifier.getMagnificationSpecForWindowLocked(windowState);
3210            }
3211            if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) {
3212                return null;
3213            }
3214            spec = (spec == null) ? MagnificationSpec.obtain() : MagnificationSpec.obtain(spec);
3215            spec.scale *= windowState.mGlobalScale;
3216            return spec;
3217        }
3218    }
3219
3220    @Override
3221    public void setMagnificationCallbacks(IMagnificationCallbacks callbacks) {
3222        if (!checkCallingPermission(android.Manifest.permission.MAGNIFY_DISPLAY,
3223                "setMagnificationCallbacks()")) {
3224            throw new SecurityException("Requires MAGNIFY_DISPLAY permission.");
3225        }
3226        synchronized (mWindowMap) {
3227            if (mDisplayMagnifier == null) {
3228                mDisplayMagnifier = new DisplayMagnifier(this, callbacks);
3229            } else {
3230                if (callbacks == null) {
3231                    if (mDisplayMagnifier != null) {
3232                        mDisplayMagnifier.destroyLocked();
3233                        mDisplayMagnifier = null;
3234                    }
3235                } else {
3236                    throw new IllegalStateException("Magnification callbacks already set!");
3237                }
3238            }
3239        }
3240    }
3241
3242    private boolean applyAnimationLocked(AppWindowToken atoken,
3243            WindowManager.LayoutParams lp, int transit, boolean enter) {
3244        // Only apply an animation if the display isn't frozen.  If it is
3245        // frozen, there is no reason to animate and it can cause strange
3246        // artifacts when we unfreeze the display if some different animation
3247        // is running.
3248        if (okToDisplay()) {
3249            DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
3250            final int width = displayInfo.appWidth;
3251            final int height = displayInfo.appHeight;
3252            if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, "applyAnimation: atoken="
3253                    + atoken);
3254            Animation a = mAppTransition.loadAnimation(lp, transit, enter, width, height);
3255            if (a != null) {
3256                if (DEBUG_ANIM) {
3257                    RuntimeException e = null;
3258                    if (!HIDE_STACK_CRAWLS) {
3259                        e = new RuntimeException();
3260                        e.fillInStackTrace();
3261                    }
3262                    Slog.v(TAG, "Loaded animation " + a + " for " + atoken, e);
3263                }
3264                atoken.mAppAnimator.setAnimation(a, width, height);
3265            }
3266        } else {
3267            atoken.mAppAnimator.clearAnimation();
3268        }
3269
3270        return atoken.mAppAnimator.animation != null;
3271    }
3272
3273    // -------------------------------------------------------------
3274    // Application Window Tokens
3275    // -------------------------------------------------------------
3276
3277    public void validateAppTokens(int stackId, List<TaskGroup> tasks) {
3278        synchronized (mWindowMap) {
3279            int t = tasks.size() - 1;
3280            if (t < 0) {
3281                Slog.w(TAG, "validateAppTokens: empty task list");
3282                return;
3283            }
3284
3285            TaskGroup task = tasks.get(0);
3286            int taskId = task.taskId;
3287            Task targetTask = mTaskIdToTask.get(taskId);
3288            DisplayContent displayContent = targetTask.getDisplayContent();
3289            if (displayContent == null) {
3290                Slog.w(TAG, "validateAppTokens: no Display for taskId=" + taskId);
3291                return;
3292            }
3293
3294            final ArrayList<Task> localTasks = mStackIdToStack.get(stackId).getTasks();
3295            int taskNdx;
3296            for (taskNdx = localTasks.size() - 1; taskNdx >= 0 && t >= 0; --taskNdx, --t) {
3297                AppTokenList localTokens = localTasks.get(taskNdx).mAppTokens;
3298                task = tasks.get(t);
3299                List<IApplicationToken> tokens = task.tokens;
3300
3301                DisplayContent lastDisplayContent = displayContent;
3302                displayContent = mTaskIdToTask.get(taskId).getDisplayContent();
3303                if (displayContent != lastDisplayContent) {
3304                    Slog.w(TAG, "validateAppTokens: displayContent changed in TaskGroup list!");
3305                    return;
3306                }
3307
3308                int tokenNdx;
3309                int v;
3310                for (tokenNdx = localTokens.size() - 1, v = task.tokens.size() - 1;
3311                        tokenNdx >= 0 && v >= 0; ) {
3312                    final AppWindowToken atoken = localTokens.get(tokenNdx);
3313                    if (atoken.removed) {
3314                        --tokenNdx;
3315                        continue;
3316                    }
3317                    if (tokens.get(v) != atoken.token) {
3318                        break;
3319                    }
3320                    --tokenNdx;
3321                    v--;
3322                }
3323
3324                if (tokenNdx >= 0 || v >= 0) {
3325                    break;
3326                }
3327            }
3328
3329            if (taskNdx >= 0 || t >= 0) {
3330                Slog.w(TAG, "validateAppTokens: Mismatch! ActivityManager=" + tasks);
3331                Slog.w(TAG, "validateAppTokens: Mismatch! WindowManager=" + localTasks);
3332                Slog.w(TAG, "validateAppTokens: Mismatch! Callers=" + Debug.getCallers(4));
3333            }
3334        }
3335    }
3336
3337    public void validateStackOrder(Integer[] remoteStackIds) {
3338        // TODO:
3339    }
3340
3341    boolean checkCallingPermission(String permission, String func) {
3342        // Quick check: if the calling permission is me, it's all okay.
3343        if (Binder.getCallingPid() == Process.myPid()) {
3344            return true;
3345        }
3346
3347        if (mContext.checkCallingPermission(permission)
3348                == PackageManager.PERMISSION_GRANTED) {
3349            return true;
3350        }
3351        String msg = "Permission Denial: " + func + " from pid="
3352                + Binder.getCallingPid()
3353                + ", uid=" + Binder.getCallingUid()
3354                + " requires " + permission;
3355        Slog.w(TAG, msg);
3356        return false;
3357    }
3358
3359    boolean okToDisplay() {
3360        return !mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOnFully();
3361    }
3362
3363    AppWindowToken findAppWindowToken(IBinder token) {
3364        WindowToken wtoken = mTokenMap.get(token);
3365        if (wtoken == null) {
3366            return null;
3367        }
3368        return wtoken.appWindowToken;
3369    }
3370
3371    @Override
3372    public void addWindowToken(IBinder token, int type) {
3373        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3374                "addWindowToken()")) {
3375            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3376        }
3377
3378        synchronized(mWindowMap) {
3379            WindowToken wtoken = mTokenMap.get(token);
3380            if (wtoken != null) {
3381                Slog.w(TAG, "Attempted to add existing input method token: " + token);
3382                return;
3383            }
3384            wtoken = new WindowToken(this, token, type, true);
3385            mTokenMap.put(token, wtoken);
3386            if (type == TYPE_WALLPAPER) {
3387                mWallpaperTokens.add(wtoken);
3388            }
3389        }
3390    }
3391
3392    @Override
3393    public void removeWindowToken(IBinder token) {
3394        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3395                "removeWindowToken()")) {
3396            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3397        }
3398
3399        final long origId = Binder.clearCallingIdentity();
3400        synchronized(mWindowMap) {
3401            DisplayContent displayContent = null;
3402            WindowToken wtoken = mTokenMap.remove(token);
3403            if (wtoken != null) {
3404                boolean delayed = false;
3405                if (!wtoken.hidden) {
3406                    final int N = wtoken.windows.size();
3407                    boolean changed = false;
3408
3409                    for (int i=0; i<N; i++) {
3410                        WindowState win = wtoken.windows.get(i);
3411                        displayContent = win.getDisplayContent();
3412
3413                        if (win.mWinAnimator.isAnimating()) {
3414                            delayed = true;
3415                        }
3416
3417                        if (win.isVisibleNow()) {
3418                            win.mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_EXIT,
3419                                    false);
3420                            //TODO (multidisplay): Magnification is supported only for the default
3421                            if (mDisplayMagnifier != null && win.isDefaultDisplay()) {
3422                                mDisplayMagnifier.onWindowTransitionLocked(win,
3423                                        WindowManagerPolicy.TRANSIT_EXIT);
3424                            }
3425                            changed = true;
3426                            if (displayContent != null) {
3427                                displayContent.layoutNeeded = true;
3428                            }
3429                        }
3430                    }
3431
3432                    wtoken.hidden = true;
3433
3434                    if (changed) {
3435                        performLayoutAndPlaceSurfacesLocked();
3436                        updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
3437                                false /*updateInputWindows*/);
3438                    }
3439
3440                    if (delayed) {
3441                        if (displayContent != null) {
3442                            displayContent.mExitingTokens.add(wtoken);
3443                        }
3444                    } else if (wtoken.windowType == TYPE_WALLPAPER) {
3445                        mWallpaperTokens.remove(wtoken);
3446                    }
3447                }
3448
3449                mInputMonitor.updateInputWindowsLw(true /*force*/);
3450            } else {
3451                Slog.w(TAG, "Attempted to remove non-existing token: " + token);
3452            }
3453        }
3454        Binder.restoreCallingIdentity(origId);
3455    }
3456
3457    private Task createTask(int taskId, int stackId, int userId, AppWindowToken atoken) {
3458        if (DEBUG_STACK) Slog.i(TAG, "createTask: taskId=" + taskId + " stackId=" + stackId
3459                + " atoken=" + atoken);
3460        final TaskStack stack = mStackIdToStack.get(stackId);
3461        if (stack == null) {
3462            throw new IllegalArgumentException("addAppToken: invalid stackId=" + stackId);
3463        }
3464        EventLog.writeEvent(EventLogTags.WM_TASK_CREATED, taskId, stackId);
3465        Task task = new Task(atoken, stack, userId);
3466        mTaskIdToTask.put(taskId, task);
3467        stack.addTask(task, true);
3468        return task;
3469    }
3470
3471    @Override
3472    public void addAppToken(int addPos, IApplicationToken token, int taskId, int stackId,
3473            int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int userId,
3474            int configChanges) {
3475        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3476                "addAppToken()")) {
3477            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3478        }
3479
3480        // Get the dispatching timeout here while we are not holding any locks so that it
3481        // can be cached by the AppWindowToken.  The timeout value is used later by the
3482        // input dispatcher in code that does hold locks.  If we did not cache the value
3483        // here we would run the chance of introducing a deadlock between the window manager
3484        // (which holds locks while updating the input dispatcher state) and the activity manager
3485        // (which holds locks while querying the application token).
3486        long inputDispatchingTimeoutNanos;
3487        try {
3488            inputDispatchingTimeoutNanos = token.getKeyDispatchingTimeout() * 1000000L;
3489        } catch (RemoteException ex) {
3490            Slog.w(TAG, "Could not get dispatching timeout.", ex);
3491            inputDispatchingTimeoutNanos = DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
3492        }
3493
3494        synchronized(mWindowMap) {
3495            AppWindowToken atoken = findAppWindowToken(token.asBinder());
3496            if (atoken != null) {
3497                Slog.w(TAG, "Attempted to add existing app token: " + token);
3498                return;
3499            }
3500            atoken = new AppWindowToken(this, token);
3501            atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
3502            atoken.groupId = taskId;
3503            atoken.appFullscreen = fullscreen;
3504            atoken.showWhenLocked = showWhenLocked;
3505            atoken.requestedOrientation = requestedOrientation;
3506            atoken.layoutConfigChanges = (configChanges &
3507                    (ActivityInfo.CONFIG_SCREEN_SIZE | ActivityInfo.CONFIG_ORIENTATION)) != 0;
3508            if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + atoken
3509                    + " to stack=" + stackId + " task=" + taskId + " at " + addPos);
3510
3511            Task task = mTaskIdToTask.get(taskId);
3512            if (task == null) {
3513                createTask(taskId, stackId, userId, atoken);
3514            } else {
3515                task.addAppToken(addPos, atoken);
3516            }
3517
3518            mTokenMap.put(token.asBinder(), atoken);
3519
3520            // Application tokens start out hidden.
3521            atoken.hidden = true;
3522            atoken.hiddenRequested = true;
3523
3524            //dump();
3525        }
3526    }
3527
3528    @Override
3529    public void setAppGroupId(IBinder token, int groupId) {
3530        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3531                "setAppGroupId()")) {
3532            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3533        }
3534
3535        synchronized(mWindowMap) {
3536            final AppWindowToken atoken = findAppWindowToken(token);
3537            if (atoken == null) {
3538                Slog.w(TAG, "Attempted to set group id of non-existing app token: " + token);
3539                return;
3540            }
3541            final Task oldTask = mTaskIdToTask.get(atoken.groupId);
3542            removeAppFromTaskLocked(atoken);
3543
3544            atoken.groupId = groupId;
3545            Task newTask = mTaskIdToTask.get(groupId);
3546            if (newTask == null) {
3547                newTask = createTask(groupId, oldTask.mStack.mStackId, oldTask.mUserId, atoken);
3548            }
3549            newTask.mAppTokens.add(atoken);
3550        }
3551    }
3552
3553    public int getOrientationFromWindowsLocked() {
3554        if (mDisplayFrozen || mOpeningApps.size() > 0 || mClosingApps.size() > 0) {
3555            // If the display is frozen, some activities may be in the middle
3556            // of restarting, and thus have removed their old window.  If the
3557            // window has the flag to hide the lock screen, then the lock screen
3558            // can re-appear and inflict its own orientation on us.  Keep the
3559            // orientation stable until this all settles down.
3560            return mLastWindowForcedOrientation;
3561        }
3562
3563        // TODO(multidisplay): Change to the correct display.
3564        final WindowList windows = getDefaultWindowListLocked();
3565        int pos = windows.size() - 1;
3566        while (pos >= 0) {
3567            WindowState win = windows.get(pos);
3568            pos--;
3569            if (win.mAppToken != null) {
3570                // We hit an application window. so the orientation will be determined by the
3571                // app window. No point in continuing further.
3572                return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
3573            }
3574            if (!win.isVisibleLw() || !win.mPolicyVisibilityAfterAnim) {
3575                continue;
3576            }
3577            int req = win.mAttrs.screenOrientation;
3578            if((req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) ||
3579                    (req == ActivityInfo.SCREEN_ORIENTATION_BEHIND)){
3580                continue;
3581            }
3582
3583            if (DEBUG_ORIENTATION) Slog.v(TAG, win + " forcing orientation to " + req);
3584            return (mLastWindowForcedOrientation=req);
3585        }
3586        return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
3587    }
3588
3589    public int getOrientationFromAppTokensLocked() {
3590        int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3591        boolean findingBehind = false;
3592        boolean lastFullscreen = false;
3593        // TODO: Multi window.
3594        DisplayContent displayContent = getDefaultDisplayContentLocked();
3595        final ArrayList<Task> tasks = displayContent.getTasks();
3596        for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
3597            AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
3598            final int firstToken = tokens.size() - 1;
3599            for (int tokenNdx = firstToken; tokenNdx >= 0; --tokenNdx) {
3600                final AppWindowToken atoken = tokens.get(tokenNdx);
3601
3602                if (DEBUG_APP_ORIENTATION) Slog.v(TAG, "Checking app orientation: " + atoken);
3603
3604                // if we're about to tear down this window and not seek for
3605                // the behind activity, don't use it for orientation
3606                if (!findingBehind
3607                        && (!atoken.hidden && atoken.hiddenRequested)) {
3608                    if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken
3609                            + " -- going to hide");
3610                    continue;
3611                }
3612
3613                if (tokenNdx == firstToken) {
3614                    // If we have hit a new Task, and the bottom
3615                    // of the previous group didn't explicitly say to use
3616                    // the orientation behind it, and the last app was
3617                    // full screen, then we'll stick with the
3618                    // user's orientation.
3619                    if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND
3620                            && lastFullscreen) {
3621                        if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
3622                                + " -- end of group, return " + lastOrientation);
3623                        return lastOrientation;
3624                    }
3625                }
3626
3627                // We ignore any hidden applications on the top.
3628                if (atoken.hiddenRequested || atoken.willBeHidden) {
3629                    if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken
3630                            + " -- hidden on top");
3631                    continue;
3632                }
3633
3634                if (tokenNdx == 0) {
3635                    // Last token in this task.
3636                    lastOrientation = atoken.requestedOrientation;
3637                }
3638
3639                int or = atoken.requestedOrientation;
3640                // If this application is fullscreen, and didn't explicitly say
3641                // to use the orientation behind it, then just take whatever
3642                // orientation it has and ignores whatever is under it.
3643                lastFullscreen = atoken.appFullscreen;
3644                if (lastFullscreen
3645                        && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
3646                    if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
3647                            + " -- full screen, return " + or);
3648                    return or;
3649                }
3650                // If this application has requested an explicit orientation,
3651                // then use it.
3652                if (or != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
3653                        && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
3654                    if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
3655                            + " -- explicitly set, return " + or);
3656                    return or;
3657                }
3658                findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND);
3659            }
3660        }
3661        if (DEBUG_ORIENTATION) Slog.v(TAG, "No app is requesting an orientation");
3662        return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3663    }
3664
3665    @Override
3666    public Configuration updateOrientationFromAppTokens(
3667            Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
3668        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3669                "updateOrientationFromAppTokens()")) {
3670            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3671        }
3672
3673        Configuration config = null;
3674        long ident = Binder.clearCallingIdentity();
3675
3676        synchronized(mWindowMap) {
3677            config = updateOrientationFromAppTokensLocked(currentConfig,
3678                    freezeThisOneIfNeeded);
3679        }
3680
3681        Binder.restoreCallingIdentity(ident);
3682        return config;
3683    }
3684
3685    private Configuration updateOrientationFromAppTokensLocked(
3686            Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
3687        Configuration config = null;
3688
3689        if (updateOrientationFromAppTokensLocked(false)) {
3690            if (freezeThisOneIfNeeded != null) {
3691                AppWindowToken atoken = findAppWindowToken(freezeThisOneIfNeeded);
3692                if (atoken != null) {
3693                    startAppFreezingScreenLocked(atoken);
3694                }
3695            }
3696            config = computeNewConfigurationLocked();
3697
3698        } else if (currentConfig != null) {
3699            // No obvious action we need to take, but if our current
3700            // state mismatches the activity manager's, update it,
3701            // disregarding font scale, which should remain set to
3702            // the value of the previous configuration.
3703            mTempConfiguration.setToDefaults();
3704            mTempConfiguration.fontScale = currentConfig.fontScale;
3705            if (computeScreenConfigurationLocked(mTempConfiguration)) {
3706                if (currentConfig.diff(mTempConfiguration) != 0) {
3707                    mWaitingForConfig = true;
3708                    final DisplayContent displayContent = getDefaultDisplayContentLocked();
3709                    displayContent.layoutNeeded = true;
3710                    int anim[] = new int[2];
3711                    if (displayContent.isDimming()) {
3712                        anim[0] = anim[1] = 0;
3713                    } else {
3714                        mPolicy.selectRotationAnimationLw(anim);
3715                    }
3716                    startFreezingDisplayLocked(false, anim[0], anim[1]);
3717                    config = new Configuration(mTempConfiguration);
3718                }
3719            }
3720        }
3721
3722        return config;
3723    }
3724
3725    /*
3726     * Determine the new desired orientation of the display, returning
3727     * a non-null new Configuration if it has changed from the current
3728     * orientation.  IF TRUE IS RETURNED SOMEONE MUST CALL
3729     * setNewConfiguration() TO TELL THE WINDOW MANAGER IT CAN UNFREEZE THE
3730     * SCREEN.  This will typically be done for you if you call
3731     * sendNewConfiguration().
3732     *
3733     * The orientation is computed from non-application windows first. If none of
3734     * the non-application windows specify orientation, the orientation is computed from
3735     * application tokens.
3736     * @see android.view.IWindowManager#updateOrientationFromAppTokens(
3737     * android.os.IBinder)
3738     */
3739    boolean updateOrientationFromAppTokensLocked(boolean inTransaction) {
3740        long ident = Binder.clearCallingIdentity();
3741        try {
3742            int req = getOrientationFromWindowsLocked();
3743            if (req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
3744                req = getOrientationFromAppTokensLocked();
3745            }
3746
3747            if (req != mForcedAppOrientation) {
3748                mForcedAppOrientation = req;
3749                //send a message to Policy indicating orientation change to take
3750                //action like disabling/enabling sensors etc.,
3751                mPolicy.setCurrentOrientationLw(req);
3752                if (updateRotationUncheckedLocked(inTransaction)) {
3753                    // changed
3754                    return true;
3755                }
3756            }
3757
3758            return false;
3759        } finally {
3760            Binder.restoreCallingIdentity(ident);
3761        }
3762    }
3763
3764    @Override
3765    public void setNewConfiguration(Configuration config) {
3766        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3767                "setNewConfiguration()")) {
3768            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3769        }
3770
3771        synchronized(mWindowMap) {
3772            mCurConfiguration = new Configuration(config);
3773            if (mWaitingForConfig) {
3774                mWaitingForConfig = false;
3775                mLastFinishedFreezeSource = "new-config";
3776            }
3777            performLayoutAndPlaceSurfacesLocked();
3778        }
3779    }
3780
3781    @Override
3782    public void setAppOrientation(IApplicationToken token, int requestedOrientation) {
3783        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3784                "setAppOrientation()")) {
3785            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3786        }
3787
3788        synchronized(mWindowMap) {
3789            AppWindowToken atoken = findAppWindowToken(token.asBinder());
3790            if (atoken == null) {
3791                Slog.w(TAG, "Attempted to set orientation of non-existing app token: " + token);
3792                return;
3793            }
3794
3795            atoken.requestedOrientation = requestedOrientation;
3796        }
3797    }
3798
3799    @Override
3800    public int getAppOrientation(IApplicationToken token) {
3801        synchronized(mWindowMap) {
3802            AppWindowToken wtoken = findAppWindowToken(token.asBinder());
3803            if (wtoken == null) {
3804                return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3805            }
3806
3807            return wtoken.requestedOrientation;
3808        }
3809    }
3810
3811    /** Call while in a Surface transaction. */
3812    void setFocusedStackLayer() {
3813        mFocusedStackLayer = 0;
3814        if (mFocusedApp != null) {
3815            final WindowList windows = mFocusedApp.allAppWindows;
3816            for (int i = windows.size() - 1; i >= 0; --i) {
3817                final WindowState win = windows.get(i);
3818                final int animLayer = win.mWinAnimator.mAnimLayer;
3819                if (win.mAttachedWindow == null && win.isVisibleLw() &&
3820                        animLayer > mFocusedStackLayer) {
3821                    mFocusedStackLayer = animLayer + LAYER_OFFSET_FOCUSED_STACK;
3822                }
3823            }
3824        }
3825        if (DEBUG_LAYERS) Slog.v(TAG, "Setting FocusedStackFrame to layer=" +
3826                mFocusedStackLayer);
3827        mFocusedStackFrame.setLayer(mFocusedStackLayer);
3828    }
3829
3830    void setFocusedStackFrame() {
3831        final TaskStack stack;
3832        if (mFocusedApp != null) {
3833            Task task = mTaskIdToTask.get(mFocusedApp.groupId);
3834            stack = task.mStack;
3835            final DisplayContent displayContent = task.getDisplayContent();
3836            if (displayContent != null) {
3837                displayContent.setTouchExcludeRegion(stack);
3838            }
3839        } else {
3840            stack = null;
3841        }
3842        if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setFocusedStackFrame");
3843        SurfaceControl.openTransaction();
3844        try {
3845            if (stack == null) {
3846                mFocusedStackFrame.setVisibility(false);
3847            } else {
3848                mFocusedStackFrame.setBounds(stack);
3849                final boolean multipleStacks = !stack.isFullscreen();
3850                mFocusedStackFrame.setVisibility(multipleStacks);
3851            }
3852        } finally {
3853            SurfaceControl.closeTransaction();
3854            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> CLOSE TRANSACTION setFocusedStackFrame");
3855        }
3856    }
3857
3858    @Override
3859    public void setFocusedApp(IBinder token, boolean moveFocusNow) {
3860        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3861                "setFocusedApp()")) {
3862            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3863        }
3864
3865        synchronized(mWindowMap) {
3866            final AppWindowToken newFocus;
3867            if (token == null) {
3868                if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Clearing focused app, was " + mFocusedApp);
3869                newFocus = null;
3870            } else {
3871                newFocus = findAppWindowToken(token);
3872                if (newFocus == null) {
3873                    Slog.w(TAG, "Attempted to set focus to non-existing app token: " + token);
3874                }
3875                if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Set focused app to: " + newFocus
3876                        + " old focus=" + mFocusedApp + " moveFocusNow=" + moveFocusNow);
3877            }
3878
3879            final boolean changed = mFocusedApp != newFocus;
3880            if (changed) {
3881                mFocusedApp = newFocus;
3882                mInputMonitor.setFocusedAppLw(null);
3883            }
3884
3885            if (moveFocusNow && changed) {
3886                final long origId = Binder.clearCallingIdentity();
3887                updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
3888                Binder.restoreCallingIdentity(origId);
3889            }
3890        }
3891    }
3892
3893    @Override
3894    public void prepareAppTransition(int transit, boolean alwaysKeepCurrent) {
3895        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3896                "prepareAppTransition()")) {
3897            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3898        }
3899
3900        synchronized(mWindowMap) {
3901            if (DEBUG_APP_TRANSITIONS) Slog.v(
3902                    TAG, "Prepare app transition: transit=" + transit
3903                    + " " + mAppTransition
3904                    + " alwaysKeepCurrent=" + alwaysKeepCurrent
3905                    + " Callers=" + Debug.getCallers(3));
3906            if (okToDisplay()) {
3907                if (!mAppTransition.isTransitionSet() || mAppTransition.isTransitionNone()) {
3908                    mAppTransition.setAppTransition(transit);
3909                } else if (!alwaysKeepCurrent) {
3910                    if (transit == AppTransition.TRANSIT_TASK_OPEN
3911                            && mAppTransition.isTransitionEqual(
3912                                    AppTransition.TRANSIT_TASK_CLOSE)) {
3913                        // Opening a new task always supersedes a close for the anim.
3914                        mAppTransition.setAppTransition(transit);
3915                    } else if (transit == AppTransition.TRANSIT_ACTIVITY_OPEN
3916                            && mAppTransition.isTransitionEqual(
3917                                AppTransition.TRANSIT_ACTIVITY_CLOSE)) {
3918                        // Opening a new activity always supersedes a close for the anim.
3919                        mAppTransition.setAppTransition(transit);
3920                    }
3921                }
3922                mAppTransition.prepare();
3923                mStartingIconInTransition = false;
3924                mSkipAppTransitionAnimation = false;
3925                mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
3926                mH.sendEmptyMessageDelayed(H.APP_TRANSITION_TIMEOUT, 5000);
3927            }
3928        }
3929    }
3930
3931    @Override
3932    public int getPendingAppTransition() {
3933        return mAppTransition.getAppTransition();
3934    }
3935
3936    @Override
3937    public void overridePendingAppTransition(String packageName,
3938            int enterAnim, int exitAnim, IRemoteCallback startedCallback) {
3939        synchronized(mWindowMap) {
3940            mAppTransition.overridePendingAppTransition(packageName, enterAnim, exitAnim,
3941                    startedCallback);
3942        }
3943    }
3944
3945    @Override
3946    public void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
3947            int startHeight) {
3948        synchronized(mWindowMap) {
3949            mAppTransition.overridePendingAppTransitionScaleUp(startX, startY, startWidth,
3950                    startHeight);
3951        }
3952    }
3953
3954    @Override
3955    public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX,
3956            int startY, IRemoteCallback startedCallback, boolean scaleUp) {
3957        synchronized(mWindowMap) {
3958            mAppTransition.overridePendingAppTransitionThumb(srcThumb, startX, startY,
3959                    startedCallback, scaleUp);
3960        }
3961    }
3962
3963    @Override
3964    public void executeAppTransition() {
3965        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3966                "executeAppTransition()")) {
3967            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3968        }
3969
3970        synchronized(mWindowMap) {
3971            if (DEBUG_APP_TRANSITIONS) {
3972                RuntimeException e = new RuntimeException("here");
3973                e.fillInStackTrace();
3974                Slog.w(TAG, "Execute app transition: " + mAppTransition, e);
3975            }
3976            if (mAppTransition.isTransitionSet()) {
3977                mAppTransition.setReady();
3978                final long origId = Binder.clearCallingIdentity();
3979                performLayoutAndPlaceSurfacesLocked();
3980                Binder.restoreCallingIdentity(origId);
3981            }
3982        }
3983    }
3984
3985    @Override
3986    public void setAppStartingWindow(IBinder token, String pkg,
3987            int theme, CompatibilityInfo compatInfo,
3988            CharSequence nonLocalizedLabel, int labelRes, int icon, int logo,
3989            int windowFlags, IBinder transferFrom, boolean createIfNeeded) {
3990        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3991                "setAppStartingWindow()")) {
3992            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3993        }
3994
3995        synchronized(mWindowMap) {
3996            if (DEBUG_STARTING_WINDOW) Slog.v(
3997                    TAG, "setAppStartingWindow: token=" + token + " pkg=" + pkg
3998                    + " transferFrom=" + transferFrom);
3999
4000            AppWindowToken wtoken = findAppWindowToken(token);
4001            if (wtoken == null) {
4002                Slog.w(TAG, "Attempted to set icon of non-existing app token: " + token);
4003                return;
4004            }
4005
4006            // If the display is frozen, we won't do anything until the
4007            // actual window is displayed so there is no reason to put in
4008            // the starting window.
4009            if (!okToDisplay()) {
4010                return;
4011            }
4012
4013            if (wtoken.startingData != null) {
4014                return;
4015            }
4016
4017            if (transferFrom != null) {
4018                AppWindowToken ttoken = findAppWindowToken(transferFrom);
4019                if (ttoken != null) {
4020                    WindowState startingWindow = ttoken.startingWindow;
4021                    if (startingWindow != null) {
4022                        if (mStartingIconInTransition) {
4023                            // In this case, the starting icon has already
4024                            // been displayed, so start letting windows get
4025                            // shown immediately without any more transitions.
4026                            mSkipAppTransitionAnimation = true;
4027                        }
4028                        if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
4029                                "Moving existing starting " + startingWindow + " from " + ttoken
4030                                + " to " + wtoken);
4031                        final long origId = Binder.clearCallingIdentity();
4032
4033                        // Transfer the starting window over to the new
4034                        // token.
4035                        wtoken.startingData = ttoken.startingData;
4036                        wtoken.startingView = ttoken.startingView;
4037                        wtoken.startingDisplayed = ttoken.startingDisplayed;
4038                        ttoken.startingDisplayed = false;
4039                        wtoken.startingWindow = startingWindow;
4040                        wtoken.reportedVisible = ttoken.reportedVisible;
4041                        ttoken.startingData = null;
4042                        ttoken.startingView = null;
4043                        ttoken.startingWindow = null;
4044                        ttoken.startingMoved = true;
4045                        startingWindow.mToken = wtoken;
4046                        startingWindow.mRootToken = wtoken;
4047                        startingWindow.mAppToken = wtoken;
4048                        startingWindow.mWinAnimator.mAppAnimator = wtoken.mAppAnimator;
4049
4050                        if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) {
4051                            Slog.v(TAG, "Removing starting window: " + startingWindow);
4052                        }
4053                        removeStartingWindowTimeout(ttoken);
4054                        startingWindow.getWindowList().remove(startingWindow);
4055                        mWindowsChanged = true;
4056                        if (DEBUG_ADD_REMOVE) Slog.v(TAG,
4057                                "Removing starting " + startingWindow + " from " + ttoken);
4058                        ttoken.windows.remove(startingWindow);
4059                        ttoken.allAppWindows.remove(startingWindow);
4060                        addWindowToListInOrderLocked(startingWindow, true);
4061
4062                        // Propagate other interesting state between the
4063                        // tokens.  If the old token is displayed, we should
4064                        // immediately force the new one to be displayed.  If
4065                        // it is animating, we need to move that animation to
4066                        // the new one.
4067                        if (ttoken.allDrawn) {
4068                            wtoken.allDrawn = true;
4069                            wtoken.deferClearAllDrawn = ttoken.deferClearAllDrawn;
4070                        }
4071                        if (ttoken.firstWindowDrawn) {
4072                            wtoken.firstWindowDrawn = true;
4073                        }
4074                        if (!ttoken.hidden) {
4075                            wtoken.hidden = false;
4076                            wtoken.hiddenRequested = false;
4077                            wtoken.willBeHidden = false;
4078                        }
4079                        if (wtoken.clientHidden != ttoken.clientHidden) {
4080                            wtoken.clientHidden = ttoken.clientHidden;
4081                            wtoken.sendAppVisibilityToClients();
4082                        }
4083                        final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator;
4084                        final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator;
4085                        if (tAppAnimator.animation != null) {
4086                            wAppAnimator.animation = tAppAnimator.animation;
4087                            wAppAnimator.animating = tAppAnimator.animating;
4088                            wAppAnimator.animLayerAdjustment = tAppAnimator.animLayerAdjustment;
4089                            tAppAnimator.animation = null;
4090                            tAppAnimator.animLayerAdjustment = 0;
4091                            wAppAnimator.updateLayers();
4092                            tAppAnimator.updateLayers();
4093                        }
4094
4095                        updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
4096                                true /*updateInputWindows*/);
4097                        getDefaultDisplayContentLocked().layoutNeeded = true;
4098                        performLayoutAndPlaceSurfacesLocked();
4099                        Binder.restoreCallingIdentity(origId);
4100                        return;
4101                    } else if (ttoken.startingData != null) {
4102                        // The previous app was getting ready to show a
4103                        // starting window, but hasn't yet done so.  Steal it!
4104                        if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
4105                                "Moving pending starting from " + ttoken
4106                                + " to " + wtoken);
4107                        wtoken.startingData = ttoken.startingData;
4108                        ttoken.startingData = null;
4109                        ttoken.startingMoved = true;
4110                        Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
4111                        // Note: we really want to do sendMessageAtFrontOfQueue() because we
4112                        // want to process the message ASAP, before any other queued
4113                        // messages.
4114                        mH.sendMessageAtFrontOfQueue(m);
4115                        return;
4116                    }
4117                    final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator;
4118                    final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator;
4119                    if (tAppAnimator.thumbnail != null) {
4120                        // The old token is animating with a thumbnail, transfer
4121                        // that to the new token.
4122                        if (wAppAnimator.thumbnail != null) {
4123                            wAppAnimator.thumbnail.destroy();
4124                        }
4125                        wAppAnimator.thumbnail = tAppAnimator.thumbnail;
4126                        wAppAnimator.thumbnailX = tAppAnimator.thumbnailX;
4127                        wAppAnimator.thumbnailY = tAppAnimator.thumbnailY;
4128                        wAppAnimator.thumbnailLayer = tAppAnimator.thumbnailLayer;
4129                        wAppAnimator.thumbnailAnimation = tAppAnimator.thumbnailAnimation;
4130                        tAppAnimator.thumbnail = null;
4131                    }
4132                }
4133            }
4134
4135            // There is no existing starting window, and the caller doesn't
4136            // want us to create one, so that's it!
4137            if (!createIfNeeded) {
4138                return;
4139            }
4140
4141            // If this is a translucent window, then don't
4142            // show a starting window -- the current effect (a full-screen
4143            // opaque starting window that fades away to the real contents
4144            // when it is ready) does not work for this.
4145            if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Checking theme of starting window: 0x"
4146                    + Integer.toHexString(theme));
4147            if (theme != 0) {
4148                AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
4149                        com.android.internal.R.styleable.Window, mCurrentUserId);
4150                if (ent == null) {
4151                    // Whoops!  App doesn't exist.  Um.  Okay.  We'll just
4152                    // pretend like we didn't see that.
4153                    return;
4154                }
4155                if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Translucent="
4156                        + ent.array.getBoolean(
4157                                com.android.internal.R.styleable.Window_windowIsTranslucent, false)
4158                        + " Floating="
4159                        + ent.array.getBoolean(
4160                                com.android.internal.R.styleable.Window_windowIsFloating, false)
4161                        + " ShowWallpaper="
4162                        + ent.array.getBoolean(
4163                                com.android.internal.R.styleable.Window_windowShowWallpaper, false));
4164                if (ent.array.getBoolean(
4165                        com.android.internal.R.styleable.Window_windowIsTranslucent, false)) {
4166                    return;
4167                }
4168                if (ent.array.getBoolean(
4169                        com.android.internal.R.styleable.Window_windowIsFloating, false)) {
4170                    return;
4171                }
4172                if (ent.array.getBoolean(
4173                        com.android.internal.R.styleable.Window_windowShowWallpaper, false)) {
4174                    if (mWallpaperTarget == null) {
4175                        // If this theme is requesting a wallpaper, and the wallpaper
4176                        // is not curently visible, then this effectively serves as
4177                        // an opaque window and our starting window transition animation
4178                        // can still work.  We just need to make sure the starting window
4179                        // is also showing the wallpaper.
4180                        windowFlags |= FLAG_SHOW_WALLPAPER;
4181                    } else {
4182                        return;
4183                    }
4184                }
4185            }
4186
4187            if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Creating StartingData");
4188            mStartingIconInTransition = true;
4189            wtoken.startingData = new StartingData(pkg, theme, compatInfo, nonLocalizedLabel,
4190                    labelRes, icon, logo, windowFlags);
4191            Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
4192            // Note: we really want to do sendMessageAtFrontOfQueue() because we
4193            // want to process the message ASAP, before any other queued
4194            // messages.
4195            if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Enqueueing ADD_STARTING");
4196            mH.sendMessageAtFrontOfQueue(m);
4197        }
4198    }
4199
4200    @Override
4201    public void setAppWillBeHidden(IBinder token) {
4202        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4203                "setAppWillBeHidden()")) {
4204            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4205        }
4206
4207        AppWindowToken wtoken;
4208
4209        synchronized(mWindowMap) {
4210            wtoken = findAppWindowToken(token);
4211            if (wtoken == null) {
4212                Slog.w(TAG, "Attempted to set will be hidden of non-existing app token: " + token);
4213                return;
4214            }
4215            wtoken.willBeHidden = true;
4216        }
4217    }
4218
4219    public void setAppFullscreen(IBinder token, boolean toOpaque) {
4220        AppWindowToken atoken = findAppWindowToken(token);
4221        if (atoken != null) {
4222            atoken.appFullscreen = toOpaque;
4223            // When making translucent, wait until windows below have been drawn.
4224            if (toOpaque) {
4225                // Making opaque so do it now.
4226                setWindowOpaque(token, true);
4227            }
4228            requestTraversal();
4229        }
4230    }
4231
4232    public void setWindowOpaque(IBinder token, boolean isOpaque) {
4233        AppWindowToken wtoken = findAppWindowToken(token);
4234        if (wtoken != null) {
4235            WindowState win = wtoken.findMainWindow();
4236            if (win != null) {
4237                win.mWinAnimator.setOpaque(isOpaque);
4238            }
4239        }
4240    }
4241
4242    boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp,
4243            boolean visible, int transit, boolean performLayout) {
4244        boolean delayed = false;
4245
4246        if (wtoken.clientHidden == visible) {
4247            wtoken.clientHidden = !visible;
4248            wtoken.sendAppVisibilityToClients();
4249        }
4250
4251        wtoken.willBeHidden = false;
4252        if (wtoken.hidden == visible) {
4253            boolean changed = false;
4254            if (DEBUG_APP_TRANSITIONS) Slog.v(
4255                TAG, "Changing app " + wtoken + " hidden=" + wtoken.hidden
4256                + " performLayout=" + performLayout);
4257
4258            boolean runningAppAnimation = false;
4259
4260            if (transit != AppTransition.TRANSIT_UNSET) {
4261                if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) {
4262                    wtoken.mAppAnimator.animation = null;
4263                }
4264                if (applyAnimationLocked(wtoken, lp, transit, visible)) {
4265                    delayed = runningAppAnimation = true;
4266                }
4267                WindowState window = wtoken.findMainWindow();
4268                //TODO (multidisplay): Magnification is supported only for the default display.
4269                if (window != null && mDisplayMagnifier != null
4270                        && window.getDisplayId() == Display.DEFAULT_DISPLAY) {
4271                    mDisplayMagnifier.onAppWindowTransitionLocked(window, transit);
4272                }
4273                changed = true;
4274            }
4275
4276            final int N = wtoken.allAppWindows.size();
4277            for (int i=0; i<N; i++) {
4278                WindowState win = wtoken.allAppWindows.get(i);
4279                if (win == wtoken.startingWindow) {
4280                    continue;
4281                }
4282
4283                //Slog.i(TAG, "Window " + win + ": vis=" + win.isVisible());
4284                //win.dump("  ");
4285                if (visible) {
4286                    if (!win.isVisibleNow()) {
4287                        if (!runningAppAnimation) {
4288                            win.mWinAnimator.applyAnimationLocked(
4289                                    WindowManagerPolicy.TRANSIT_ENTER, true);
4290                            //TODO (multidisplay): Magnification is supported only for the default
4291                            if (mDisplayMagnifier != null
4292                                    && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
4293                                mDisplayMagnifier.onWindowTransitionLocked(win,
4294                                        WindowManagerPolicy.TRANSIT_ENTER);
4295                            }
4296                        }
4297                        changed = true;
4298                        final DisplayContent displayContent = win.getDisplayContent();
4299                        if (displayContent != null) {
4300                            displayContent.layoutNeeded = true;
4301                        }
4302                    }
4303                } else if (win.isVisibleNow()) {
4304                    if (!runningAppAnimation) {
4305                        win.mWinAnimator.applyAnimationLocked(
4306                                WindowManagerPolicy.TRANSIT_EXIT, false);
4307                        //TODO (multidisplay): Magnification is supported only for the default
4308                        if (mDisplayMagnifier != null
4309                                && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
4310                            mDisplayMagnifier.onWindowTransitionLocked(win,
4311                                    WindowManagerPolicy.TRANSIT_EXIT);
4312                        }
4313                    }
4314                    changed = true;
4315                    final DisplayContent displayContent = win.getDisplayContent();
4316                    if (displayContent != null) {
4317                        displayContent.layoutNeeded = true;
4318                    }
4319                }
4320            }
4321
4322            wtoken.hidden = wtoken.hiddenRequested = !visible;
4323            if (!visible) {
4324                unsetAppFreezingScreenLocked(wtoken, true, true);
4325            } else {
4326                // If we are being set visible, and the starting window is
4327                // not yet displayed, then make sure it doesn't get displayed.
4328                WindowState swin = wtoken.startingWindow;
4329                if (swin != null && !swin.isDrawnLw()) {
4330                    swin.mPolicyVisibility = false;
4331                    swin.mPolicyVisibilityAfterAnim = false;
4332                 }
4333            }
4334
4335            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "setTokenVisibilityLocked: " + wtoken
4336                      + ": hidden=" + wtoken.hidden + " hiddenRequested="
4337                      + wtoken.hiddenRequested);
4338
4339            if (changed) {
4340                mInputMonitor.setUpdateInputWindowsNeededLw();
4341                if (performLayout) {
4342                    updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
4343                            false /*updateInputWindows*/);
4344                    performLayoutAndPlaceSurfacesLocked();
4345                }
4346                mInputMonitor.updateInputWindowsLw(false /*force*/);
4347            }
4348        }
4349
4350        if (wtoken.mAppAnimator.animation != null) {
4351            delayed = true;
4352        }
4353
4354        for (int i = wtoken.allAppWindows.size() - 1; i >= 0 && !delayed; i--) {
4355            if (wtoken.allAppWindows.get(i).mWinAnimator.isWindowAnimating()) {
4356                delayed = true;
4357            }
4358        }
4359
4360        return delayed;
4361    }
4362
4363    @Override
4364    public void setAppVisibility(IBinder token, boolean visible) {
4365        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4366                "setAppVisibility()")) {
4367            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4368        }
4369
4370        AppWindowToken wtoken;
4371
4372        synchronized(mWindowMap) {
4373            wtoken = findAppWindowToken(token);
4374            if (wtoken == null) {
4375                Slog.w(TAG, "Attempted to set visibility of non-existing app token: " + token);
4376                return;
4377            }
4378
4379            if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) {
4380                RuntimeException e = null;
4381                if (!HIDE_STACK_CRAWLS) {
4382                    e = new RuntimeException();
4383                    e.fillInStackTrace();
4384                }
4385                Slog.v(TAG, "setAppVisibility(" + token + ", visible=" + visible
4386                        + "): " + mAppTransition
4387                        + " hidden=" + wtoken.hidden
4388                        + " hiddenRequested=" + wtoken.hiddenRequested, e);
4389            }
4390
4391            // If we are preparing an app transition, then delay changing
4392            // the visibility of this token until we execute that transition.
4393            if (okToDisplay() && mAppTransition.isTransitionSet()) {
4394                wtoken.hiddenRequested = !visible;
4395
4396                if (!wtoken.startingDisplayed) {
4397                    if (DEBUG_APP_TRANSITIONS) Slog.v(
4398                            TAG, "Setting dummy animation on: " + wtoken);
4399                    wtoken.mAppAnimator.setDummyAnimation();
4400                }
4401                mOpeningApps.remove(wtoken);
4402                mClosingApps.remove(wtoken);
4403                wtoken.waitingToShow = wtoken.waitingToHide = false;
4404                wtoken.inPendingTransaction = true;
4405                if (visible) {
4406                    mOpeningApps.add(wtoken);
4407                    wtoken.startingMoved = false;
4408
4409                    // If the token is currently hidden (should be the
4410                    // common case), then we need to set up to wait for
4411                    // its windows to be ready.
4412                    if (wtoken.hidden) {
4413                        wtoken.allDrawn = false;
4414                        wtoken.deferClearAllDrawn = false;
4415                        wtoken.waitingToShow = true;
4416
4417                        if (wtoken.clientHidden) {
4418                            // In the case where we are making an app visible
4419                            // but holding off for a transition, we still need
4420                            // to tell the client to make its windows visible so
4421                            // they get drawn.  Otherwise, we will wait on
4422                            // performing the transition until all windows have
4423                            // been drawn, they never will be, and we are sad.
4424                            wtoken.clientHidden = false;
4425                            wtoken.sendAppVisibilityToClients();
4426                        }
4427                    }
4428                } else {
4429                    mClosingApps.add(wtoken);
4430
4431                    // If the token is currently visible (should be the
4432                    // common case), then set up to wait for it to be hidden.
4433                    if (!wtoken.hidden) {
4434                        wtoken.waitingToHide = true;
4435                    }
4436                }
4437                return;
4438            }
4439
4440            final long origId = Binder.clearCallingIdentity();
4441            setTokenVisibilityLocked(wtoken, null, visible, AppTransition.TRANSIT_UNSET,
4442                    true);
4443            wtoken.updateReportedVisibilityLocked();
4444            Binder.restoreCallingIdentity(origId);
4445        }
4446    }
4447
4448    void unsetAppFreezingScreenLocked(AppWindowToken wtoken,
4449            boolean unfreezeSurfaceNow, boolean force) {
4450        if (wtoken.mAppAnimator.freezingScreen) {
4451            if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + wtoken
4452                    + " force=" + force);
4453            final int N = wtoken.allAppWindows.size();
4454            boolean unfrozeWindows = false;
4455            for (int i=0; i<N; i++) {
4456                WindowState w = wtoken.allAppWindows.get(i);
4457                if (w.mAppFreezing) {
4458                    w.mAppFreezing = false;
4459                    if (w.mHasSurface && !w.mOrientationChanging) {
4460                        if (DEBUG_ORIENTATION) Slog.v(TAG, "set mOrientationChanging of " + w);
4461                        w.mOrientationChanging = true;
4462                        mInnerFields.mOrientationChangeComplete = false;
4463                    }
4464                    w.mLastFreezeDuration = 0;
4465                    unfrozeWindows = true;
4466                    final DisplayContent displayContent = w.getDisplayContent();
4467                    if (displayContent != null) {
4468                        displayContent.layoutNeeded = true;
4469                    }
4470                }
4471            }
4472            if (force || unfrozeWindows) {
4473                if (DEBUG_ORIENTATION) Slog.v(TAG, "No longer freezing: " + wtoken);
4474                wtoken.mAppAnimator.freezingScreen = false;
4475                wtoken.mAppAnimator.lastFreezeDuration = (int)(SystemClock.elapsedRealtime()
4476                        - mDisplayFreezeTime);
4477                mAppsFreezingScreen--;
4478                mLastFinishedFreezeSource = wtoken;
4479            }
4480            if (unfreezeSurfaceNow) {
4481                if (unfrozeWindows) {
4482                    performLayoutAndPlaceSurfacesLocked();
4483                }
4484                stopFreezingDisplayLocked();
4485            }
4486        }
4487    }
4488
4489    private void startAppFreezingScreenLocked(AppWindowToken wtoken) {
4490        if (DEBUG_ORIENTATION) {
4491            RuntimeException e = null;
4492            if (!HIDE_STACK_CRAWLS) {
4493                e = new RuntimeException();
4494                e.fillInStackTrace();
4495            }
4496            Slog.i(TAG, "Set freezing of " + wtoken.appToken
4497                    + ": hidden=" + wtoken.hidden + " freezing="
4498                    + wtoken.mAppAnimator.freezingScreen, e);
4499        }
4500        if (!wtoken.hiddenRequested) {
4501            if (!wtoken.mAppAnimator.freezingScreen) {
4502                wtoken.mAppAnimator.freezingScreen = true;
4503                wtoken.mAppAnimator.lastFreezeDuration = 0;
4504                mAppsFreezingScreen++;
4505                if (mAppsFreezingScreen == 1) {
4506                    startFreezingDisplayLocked(false, 0, 0);
4507                    mH.removeMessages(H.APP_FREEZE_TIMEOUT);
4508                    mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 5000);
4509                }
4510            }
4511            final int N = wtoken.allAppWindows.size();
4512            for (int i=0; i<N; i++) {
4513                WindowState w = wtoken.allAppWindows.get(i);
4514                w.mAppFreezing = true;
4515            }
4516        }
4517    }
4518
4519    @Override
4520    public void startAppFreezingScreen(IBinder token, int configChanges) {
4521        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4522                "setAppFreezingScreen()")) {
4523            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4524        }
4525
4526        synchronized(mWindowMap) {
4527            if (configChanges == 0 && okToDisplay()) {
4528                if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping set freeze of " + token);
4529                return;
4530            }
4531
4532            AppWindowToken wtoken = findAppWindowToken(token);
4533            if (wtoken == null || wtoken.appToken == null) {
4534                Slog.w(TAG, "Attempted to freeze screen with non-existing app token: " + wtoken);
4535                return;
4536            }
4537            final long origId = Binder.clearCallingIdentity();
4538            startAppFreezingScreenLocked(wtoken);
4539            Binder.restoreCallingIdentity(origId);
4540        }
4541    }
4542
4543    @Override
4544    public void stopAppFreezingScreen(IBinder token, boolean force) {
4545        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4546                "setAppFreezingScreen()")) {
4547            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4548        }
4549
4550        synchronized(mWindowMap) {
4551            AppWindowToken wtoken = findAppWindowToken(token);
4552            if (wtoken == null || wtoken.appToken == null) {
4553                return;
4554            }
4555            final long origId = Binder.clearCallingIdentity();
4556            if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + token
4557                    + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.mAppAnimator.freezingScreen);
4558            unsetAppFreezingScreenLocked(wtoken, true, force);
4559            Binder.restoreCallingIdentity(origId);
4560        }
4561    }
4562
4563    void removeAppFromTaskLocked(AppWindowToken wtoken) {
4564        final Task task = mTaskIdToTask.get(wtoken.groupId);
4565        if (task != null) {
4566            if (!task.removeAppToken(wtoken)) {
4567                Slog.e(TAG, "removeAppFromTaskLocked: token=" + wtoken + " not found.");
4568            }
4569        }
4570    }
4571
4572    @Override
4573    public void removeAppToken(IBinder token) {
4574        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4575                "removeAppToken()")) {
4576            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4577        }
4578
4579        AppWindowToken wtoken = null;
4580        AppWindowToken startingToken = null;
4581        boolean delayed = false;
4582
4583        final long origId = Binder.clearCallingIdentity();
4584        synchronized(mWindowMap) {
4585            WindowToken basewtoken = mTokenMap.remove(token);
4586            if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) {
4587                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Removing app token: " + wtoken);
4588                delayed = setTokenVisibilityLocked(wtoken, null, false,
4589                        AppTransition.TRANSIT_UNSET, true);
4590                wtoken.inPendingTransaction = false;
4591                mOpeningApps.remove(wtoken);
4592                wtoken.waitingToShow = false;
4593                if (mClosingApps.contains(wtoken)) {
4594                    delayed = true;
4595                } else if (mAppTransition.isTransitionSet()) {
4596                    mClosingApps.add(wtoken);
4597                    wtoken.waitingToHide = true;
4598                    delayed = true;
4599                }
4600                if (DEBUG_APP_TRANSITIONS) Slog.v(
4601                        TAG, "Removing app " + wtoken + " delayed=" + delayed
4602                        + " animation=" + wtoken.mAppAnimator.animation
4603                        + " animating=" + wtoken.mAppAnimator.animating);
4604                if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, "removeAppToken: "
4605                        + wtoken + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
4606                final TaskStack stack = mTaskIdToTask.get(wtoken.groupId).mStack;
4607                if (delayed) {
4608                    // set the token aside because it has an active animation to be finished
4609                    if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
4610                            "removeAppToken make exiting: " + wtoken);
4611                    stack.mExitingAppTokens.add(wtoken);
4612                    wtoken.mDeferRemoval = true;
4613                } else {
4614                    // Make sure there is no animation running on this token,
4615                    // so any windows associated with it will be removed as
4616                    // soon as their animations are complete
4617                    wtoken.mAppAnimator.clearAnimation();
4618                    wtoken.mAppAnimator.animating = false;
4619                    removeAppFromTaskLocked(wtoken);
4620                }
4621
4622                wtoken.removed = true;
4623                if (wtoken.startingData != null) {
4624                    startingToken = wtoken;
4625                }
4626                unsetAppFreezingScreenLocked(wtoken, true, true);
4627                if (mFocusedApp == wtoken) {
4628                    if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Removing focused app token:" + wtoken);
4629                    mFocusedApp = null;
4630                    updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
4631                    mInputMonitor.setFocusedAppLw(null);
4632                }
4633            } else {
4634                Slog.w(TAG, "Attempted to remove non-existing app token: " + token);
4635            }
4636
4637            if (!delayed && wtoken != null) {
4638                wtoken.updateReportedVisibilityLocked();
4639            }
4640        }
4641        Binder.restoreCallingIdentity(origId);
4642
4643        // Will only remove if startingToken non null.
4644        scheduleRemoveStartingWindow(startingToken);
4645    }
4646
4647    void removeStartingWindowTimeout(AppWindowToken wtoken) {
4648        if (wtoken != null) {
4649            if (DEBUG_STARTING_WINDOW) Slog.v(TAG, Debug.getCallers(1) +
4650                    ": Remove starting window timeout " + wtoken + (wtoken != null ?
4651                    " startingWindow=" + wtoken.startingWindow : ""));
4652            mH.removeMessages(H.REMOVE_STARTING_TIMEOUT, wtoken);
4653        }
4654    }
4655
4656    void scheduleRemoveStartingWindow(AppWindowToken wtoken) {
4657        if (wtoken != null && wtoken.startingWindow != null) {
4658            if (DEBUG_STARTING_WINDOW) Slog.v(TAG, Debug.getCallers(1) +
4659                    ": Schedule remove starting " + wtoken + (wtoken != null ?
4660                    " startingWindow=" + wtoken.startingWindow : ""));
4661            removeStartingWindowTimeout(wtoken);
4662            Message m = mH.obtainMessage(H.REMOVE_STARTING, wtoken);
4663            mH.sendMessage(m);
4664        }
4665    }
4666
4667    private boolean tmpRemoveAppWindowsLocked(WindowToken token) {
4668        WindowList windows = token.windows;
4669        final int NW = windows.size();
4670        if (NW > 0) {
4671            mWindowsChanged = true;
4672        }
4673        for (int i = 0; i < NW; i++) {
4674            WindowState win = windows.get(i);
4675            if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Tmp removing app window " + win);
4676            win.getWindowList().remove(win);
4677            int j = win.mChildWindows.size();
4678            while (j > 0) {
4679                j--;
4680                WindowState cwin = win.mChildWindows.get(j);
4681                if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
4682                        "Tmp removing child window " + cwin);
4683                cwin.getWindowList().remove(cwin);
4684            }
4685        }
4686        return NW > 0;
4687    }
4688
4689    void dumpAppTokensLocked() {
4690        final int numStacks = mStackIdToStack.size();
4691        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
4692            final TaskStack stack = mStackIdToStack.valueAt(stackNdx);
4693            Slog.v(TAG, "  Stack #" + stack.mStackId + " tasks from bottom to top:");
4694            final ArrayList<Task> tasks = stack.getTasks();
4695            final int numTasks = tasks.size();
4696            for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
4697                final Task task = tasks.get(taskNdx);
4698                Slog.v(TAG, "    Task #" + task.taskId + " activities from bottom to top:");
4699                AppTokenList tokens = task.mAppTokens;
4700                final int numTokens = tokens.size();
4701                for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
4702                    Slog.v(TAG, "      activity #" + tokenNdx + ": " + tokens.get(tokenNdx).token);
4703                }
4704            }
4705        }
4706    }
4707
4708    void dumpWindowsLocked() {
4709        final int numDisplays = mDisplayContents.size();
4710        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
4711            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
4712            Slog.v(TAG, " Display #" + displayContent.getDisplayId());
4713            final WindowList windows = displayContent.getWindowList();
4714            for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
4715                Slog.v(TAG, "  #" + winNdx + ": " + windows.get(winNdx));
4716            }
4717        }
4718    }
4719
4720    private int findAppWindowInsertionPointLocked(AppWindowToken target) {
4721        final int taskId = target.groupId;
4722        Task targetTask = mTaskIdToTask.get(taskId);
4723        if (targetTask == null) {
4724            Slog.w(TAG, "findAppWindowInsertionPointLocked: no Task for " + target + " taskId="
4725                    + taskId);
4726            return 0;
4727        }
4728        DisplayContent displayContent = targetTask.getDisplayContent();
4729        if (displayContent == null) {
4730            Slog.w(TAG, "findAppWindowInsertionPointLocked: no DisplayContent for " + target);
4731            return 0;
4732        }
4733        final WindowList windows = displayContent.getWindowList();
4734        final int NW = windows.size();
4735
4736        boolean found = false;
4737        final ArrayList<Task> tasks = displayContent.getTasks();
4738        for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
4739            final Task task = tasks.get(taskNdx);
4740            if (!found && task.taskId != taskId) {
4741                continue;
4742            }
4743            AppTokenList tokens = task.mAppTokens;
4744            for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
4745                final AppWindowToken wtoken = tokens.get(tokenNdx);
4746                if (!found && wtoken == target) {
4747                    found = true;
4748                }
4749                if (found) {
4750                    // Find the first app token below the new position that has
4751                    // a window displayed.
4752                    if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows in " + wtoken.token);
4753                    if (wtoken.sendingToBottom) {
4754                        if (DEBUG_REORDER) Slog.v(TAG, "Skipping token -- currently sending to bottom");
4755                        continue;
4756                    }
4757                    for (int i = wtoken.windows.size() - 1; i >= 0; --i) {
4758                        WindowState win = wtoken.windows.get(i);
4759                        for (int j = win.mChildWindows.size() - 1; j >= 0; --j) {
4760                            WindowState cwin = win.mChildWindows.get(j);
4761                            if (cwin.mSubLayer >= 0) {
4762                                for (int pos = NW - 1; pos >= 0; pos--) {
4763                                    if (windows.get(pos) == cwin) {
4764                                        if (DEBUG_REORDER) Slog.v(TAG,
4765                                                "Found child win @" + (pos + 1));
4766                                        return pos + 1;
4767                                    }
4768                                }
4769                            }
4770                        }
4771                        for (int pos = NW - 1; pos >= 0; pos--) {
4772                            if (windows.get(pos) == win) {
4773                                if (DEBUG_REORDER) Slog.v(TAG, "Found win @" + (pos + 1));
4774                                return pos + 1;
4775                            }
4776                        }
4777                    }
4778                }
4779            }
4780        }
4781        // Never put an app window underneath wallpaper.
4782        for (int pos = NW - 1; pos >= 0; pos--) {
4783            if (windows.get(pos).mIsWallpaper) {
4784                if (DEBUG_REORDER) Slog.v(TAG, "Found wallpaper @" + pos);
4785                return pos + 1;
4786            }
4787        }
4788        return 0;
4789    }
4790
4791    private final int reAddWindowLocked(int index, WindowState win) {
4792        final WindowList windows = win.getWindowList();
4793        final int NCW = win.mChildWindows.size();
4794        boolean added = false;
4795        for (int j=0; j<NCW; j++) {
4796            WindowState cwin = win.mChildWindows.get(j);
4797            if (!added && cwin.mSubLayer >= 0) {
4798                if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding child window at "
4799                        + index + ": " + cwin);
4800                win.mRebuilding = false;
4801                windows.add(index, win);
4802                index++;
4803                added = true;
4804            }
4805            if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
4806                    + index + ": " + cwin);
4807            cwin.mRebuilding = false;
4808            windows.add(index, cwin);
4809            index++;
4810        }
4811        if (!added) {
4812            if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
4813                    + index + ": " + win);
4814            win.mRebuilding = false;
4815            windows.add(index, win);
4816            index++;
4817        }
4818        mWindowsChanged = true;
4819        return index;
4820    }
4821
4822    private final int reAddAppWindowsLocked(final DisplayContent displayContent, int index,
4823                                            WindowToken token) {
4824        final int NW = token.windows.size();
4825        for (int i=0; i<NW; i++) {
4826            final WindowState win = token.windows.get(i);
4827            final DisplayContent winDisplayContent = win.getDisplayContent();
4828            if (winDisplayContent == displayContent || winDisplayContent == null) {
4829                win.mDisplayContent = displayContent;
4830                index = reAddWindowLocked(index, win);
4831            }
4832        }
4833        return index;
4834    }
4835
4836    void tmpRemoveTaskWindowsLocked(Task task) {
4837        AppTokenList tokens = task.mAppTokens;
4838        for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
4839            tmpRemoveAppWindowsLocked(tokens.get(tokenNdx));
4840        }
4841    }
4842
4843    void moveStackWindowsLocked(DisplayContent displayContent) {
4844        // First remove all of the windows from the list.
4845        final ArrayList<Task> tasks = displayContent.getTasks();
4846        final int numTasks = tasks.size();
4847        for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
4848            tmpRemoveTaskWindowsLocked(tasks.get(taskNdx));
4849        }
4850
4851        // And now add them back at the correct place.
4852        // Where to start adding?
4853        for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
4854            AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
4855            int pos = findAppWindowInsertionPointLocked(tokens.get(0));
4856            final int numTokens = tokens.size();
4857            for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
4858                final AppWindowToken wtoken = tokens.get(tokenNdx);
4859                if (wtoken != null) {
4860                    final int newPos = reAddAppWindowsLocked(displayContent, pos, wtoken);
4861                    if (newPos != pos) {
4862                        displayContent.layoutNeeded = true;
4863                    }
4864                    pos = newPos;
4865                }
4866            }
4867        }
4868
4869        if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
4870                false /*updateInputWindows*/)) {
4871            assignLayersLocked(displayContent.getWindowList());
4872        }
4873
4874        mInputMonitor.setUpdateInputWindowsNeededLw();
4875        performLayoutAndPlaceSurfacesLocked();
4876        mInputMonitor.updateInputWindowsLw(false /*force*/);
4877
4878        //dump();
4879    }
4880
4881    public void moveTaskToTop(int taskId) {
4882        final long origId = Binder.clearCallingIdentity();
4883        try {
4884            synchronized(mWindowMap) {
4885                Task task = mTaskIdToTask.get(taskId);
4886                if (task == null) {
4887                    // Normal behavior, addAppToken will be called next and task will be created.
4888                    return;
4889                }
4890                final TaskStack stack = task.mStack;
4891                final DisplayContent displayContent = task.getDisplayContent();
4892                displayContent.moveStack(stack, true);
4893                if (displayContent.isDefaultDisplay) {
4894                    final TaskStack homeStack = displayContent.getHomeStack();
4895                    if (homeStack != stack) {
4896                        // When a non-home stack moves to the top, the home stack moves to the
4897                        // bottom.
4898                        displayContent.moveStack(homeStack, false);
4899                    }
4900                }
4901                stack.moveTaskToTop(task);
4902            }
4903        } finally {
4904            Binder.restoreCallingIdentity(origId);
4905        }
4906    }
4907
4908    public void moveTaskToBottom(int taskId) {
4909        final long origId = Binder.clearCallingIdentity();
4910        try {
4911            synchronized(mWindowMap) {
4912                Task task = mTaskIdToTask.get(taskId);
4913                if (task == null) {
4914                    Slog.e(TAG, "moveTaskToBottom: taskId=" + taskId
4915                            + " not found in mTaskIdToTask");
4916                    return;
4917                }
4918                final TaskStack stack = task.mStack;
4919                stack.moveTaskToBottom(task);
4920                moveStackWindowsLocked(stack.getDisplayContent());
4921            }
4922        } finally {
4923            Binder.restoreCallingIdentity(origId);
4924        }
4925    }
4926
4927    /**
4928     * Create a new TaskStack and place it on a DisplayContent.
4929     * @param stackId The unique identifier of the new stack.
4930     * @param displayId The unique identifier of the DisplayContent.
4931     */
4932    public void attachStack(int stackId, int displayId) {
4933        final long origId = Binder.clearCallingIdentity();
4934        try {
4935            synchronized (mWindowMap) {
4936                final DisplayContent displayContent = mDisplayContents.get(displayId);
4937                if (displayContent != null) {
4938                    TaskStack stack = mStackIdToStack.get(stackId);
4939                    if (stack == null) {
4940                        if (DEBUG_STACK) Slog.d(TAG, "attachStack: stackId=" + stackId);
4941                        stack = new TaskStack(this, stackId);
4942                        mStackIdToStack.put(stackId, stack);
4943                    }
4944                    stack.attachDisplayContent(displayContent);
4945                    displayContent.attachStack(stack);
4946                    moveStackWindowsLocked(displayContent);
4947                    final WindowList windows = displayContent.getWindowList();
4948                    for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
4949                        windows.get(winNdx).reportResized();
4950                    }
4951                }
4952            }
4953        } finally {
4954            Binder.restoreCallingIdentity(origId);
4955        }
4956    }
4957
4958    void detachStackLocked(DisplayContent displayContent, TaskStack stack) {
4959        displayContent.detachStack(stack);
4960        stack.detachDisplay();
4961    }
4962
4963    public void detachStack(int stackId) {
4964        synchronized (mWindowMap) {
4965            TaskStack stack = mStackIdToStack.get(stackId);
4966            if (stack != null) {
4967                final DisplayContent displayContent = stack.getDisplayContent();
4968                if (displayContent != null) {
4969                    if (stack.isAnimating()) {
4970                        stack.mDeferDetach = true;
4971                        return;
4972                    }
4973                    detachStackLocked(displayContent, stack);
4974                }
4975            }
4976        }
4977    }
4978
4979    public void removeStack(int stackId) {
4980        mStackIdToStack.remove(stackId);
4981    }
4982
4983    void removeTaskLocked(Task task) {
4984        final int taskId = task.taskId;
4985        final TaskStack stack = task.mStack;
4986        if (stack.isAnimating()) {
4987            if (DEBUG_STACK) Slog.i(TAG, "removeTask: deferring removing taskId=" + taskId);
4988            task.mDeferRemoval = true;
4989            return;
4990        }
4991        if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + taskId);
4992        EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, taskId, "removeTask");
4993        task.mDeferRemoval = false;
4994        task.mStack.removeTask(task);
4995        mTaskIdToTask.delete(task.taskId);
4996    }
4997
4998    public void removeTask(int taskId) {
4999        synchronized (mWindowMap) {
5000            Task task = mTaskIdToTask.get(taskId);
5001            if (task == null) {
5002                if (DEBUG_STACK) Slog.i(TAG, "removeTask: could not find taskId=" + taskId);
5003                return;
5004            }
5005            removeTaskLocked(task);
5006        }
5007    }
5008
5009    public void addTask(int taskId, int stackId, boolean toTop) {
5010        synchronized (mWindowMap) {
5011            if (DEBUG_STACK) Slog.i(TAG, "addTask: adding taskId=" + taskId
5012                    + " to " + (toTop ? "top" : "bottom"));
5013            Task task = mTaskIdToTask.get(taskId);
5014            if (task == null) {
5015                return;
5016            }
5017            TaskStack stack = mStackIdToStack.get(stackId);
5018            stack.addTask(task, toTop);
5019            final DisplayContent displayContent = stack.getDisplayContent();
5020            displayContent.layoutNeeded = true;
5021            performLayoutAndPlaceSurfacesLocked();
5022        }
5023    }
5024
5025    public void resizeStack(int stackId, Rect bounds) {
5026        synchronized (mWindowMap) {
5027            final TaskStack stack = mStackIdToStack.get(stackId);
5028            if (stack == null) {
5029                throw new IllegalArgumentException("resizeStack: stackId " + stackId
5030                        + " not found.");
5031            }
5032            if (stack.setBounds(bounds)) {
5033                stack.resizeWindows();
5034                stack.getDisplayContent().layoutNeeded = true;
5035                performLayoutAndPlaceSurfacesLocked();
5036            }
5037        }
5038    }
5039
5040    public void getStackBounds(int stackId, Rect bounds) {
5041        final TaskStack stack = mStackIdToStack.get(stackId);
5042        if (stack != null) {
5043            stack.getBounds(bounds);
5044            return;
5045        }
5046        bounds.setEmpty();
5047    }
5048
5049    // -------------------------------------------------------------
5050    // Misc IWindowSession methods
5051    // -------------------------------------------------------------
5052
5053    @Override
5054    public void startFreezingScreen(int exitAnim, int enterAnim) {
5055        if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
5056                "startFreezingScreen()")) {
5057            throw new SecurityException("Requires FREEZE_SCREEN permission");
5058        }
5059
5060        synchronized(mWindowMap) {
5061            if (!mClientFreezingScreen) {
5062                mClientFreezingScreen = true;
5063                final long origId = Binder.clearCallingIdentity();
5064                try {
5065                    startFreezingDisplayLocked(false, exitAnim, enterAnim);
5066                    mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
5067                    mH.sendEmptyMessageDelayed(H.CLIENT_FREEZE_TIMEOUT, 5000);
5068                } finally {
5069                    Binder.restoreCallingIdentity(origId);
5070                }
5071            }
5072        }
5073    }
5074
5075    @Override
5076    public void stopFreezingScreen() {
5077        if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
5078                "stopFreezingScreen()")) {
5079            throw new SecurityException("Requires FREEZE_SCREEN permission");
5080        }
5081
5082        synchronized(mWindowMap) {
5083            if (mClientFreezingScreen) {
5084                mClientFreezingScreen = false;
5085                mLastFinishedFreezeSource = "client";
5086                final long origId = Binder.clearCallingIdentity();
5087                try {
5088                    stopFreezingDisplayLocked();
5089                } finally {
5090                    Binder.restoreCallingIdentity(origId);
5091                }
5092            }
5093        }
5094    }
5095
5096    @Override
5097    public void disableKeyguard(IBinder token, String tag) {
5098        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5099            != PackageManager.PERMISSION_GRANTED) {
5100            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5101        }
5102
5103        mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
5104                KeyguardDisableHandler.KEYGUARD_DISABLE, new Pair<IBinder, String>(token, tag)));
5105    }
5106
5107    @Override
5108    public void reenableKeyguard(IBinder token) {
5109        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5110            != PackageManager.PERMISSION_GRANTED) {
5111            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5112        }
5113
5114        mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
5115                KeyguardDisableHandler.KEYGUARD_REENABLE, token));
5116    }
5117
5118    /**
5119     * @see android.app.KeyguardManager#exitKeyguardSecurely
5120     */
5121    @Override
5122    public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) {
5123        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5124            != PackageManager.PERMISSION_GRANTED) {
5125            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5126        }
5127        mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() {
5128            @Override
5129            public void onKeyguardExitResult(boolean success) {
5130                try {
5131                    callback.onKeyguardExitResult(success);
5132                } catch (RemoteException e) {
5133                    // Client has died, we don't care.
5134                }
5135            }
5136        });
5137    }
5138
5139    @Override
5140    public boolean inKeyguardRestrictedInputMode() {
5141        return mPolicy.inKeyguardRestrictedKeyInputMode();
5142    }
5143
5144    @Override
5145    public boolean isKeyguardLocked() {
5146        return mPolicy.isKeyguardLocked();
5147    }
5148
5149    @Override
5150    public boolean isKeyguardSecure() {
5151        return mPolicy.isKeyguardSecure();
5152    }
5153
5154    @Override
5155    public void dismissKeyguard() {
5156        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5157                != PackageManager.PERMISSION_GRANTED) {
5158            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5159        }
5160        synchronized(mWindowMap) {
5161            mPolicy.dismissKeyguardLw();
5162        }
5163    }
5164
5165    @Override
5166    public void closeSystemDialogs(String reason) {
5167        synchronized(mWindowMap) {
5168            final int numDisplays = mDisplayContents.size();
5169            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5170                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
5171                final int numWindows = windows.size();
5172                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
5173                    final WindowState w = windows.get(winNdx);
5174                    if (w.mHasSurface) {
5175                        try {
5176                            w.mClient.closeSystemDialogs(reason);
5177                        } catch (RemoteException e) {
5178                        }
5179                    }
5180                }
5181            }
5182        }
5183    }
5184
5185    static float fixScale(float scale) {
5186        if (scale < 0) scale = 0;
5187        else if (scale > 20) scale = 20;
5188        return Math.abs(scale);
5189    }
5190
5191    @Override
5192    public void setAnimationScale(int which, float scale) {
5193        if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
5194                "setAnimationScale()")) {
5195            throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
5196        }
5197
5198        scale = fixScale(scale);
5199        switch (which) {
5200            case 0: mWindowAnimationScale = scale; break;
5201            case 1: mTransitionAnimationScale = scale; break;
5202            case 2: mAnimatorDurationScale = scale; break;
5203        }
5204
5205        // Persist setting
5206        mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
5207    }
5208
5209    @Override
5210    public void setAnimationScales(float[] scales) {
5211        if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
5212                "setAnimationScale()")) {
5213            throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
5214        }
5215
5216        if (scales != null) {
5217            if (scales.length >= 1) {
5218                mWindowAnimationScale = fixScale(scales[0]);
5219            }
5220            if (scales.length >= 2) {
5221                mTransitionAnimationScale = fixScale(scales[1]);
5222            }
5223            if (scales.length >= 3) {
5224                setAnimatorDurationScale(fixScale(scales[2]));
5225            }
5226        }
5227
5228        // Persist setting
5229        mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
5230    }
5231
5232    private void setAnimatorDurationScale(float scale) {
5233        mAnimatorDurationScale = scale;
5234        ValueAnimator.setDurationScale(scale);
5235    }
5236
5237    @Override
5238    public float getAnimationScale(int which) {
5239        switch (which) {
5240            case 0: return mWindowAnimationScale;
5241            case 1: return mTransitionAnimationScale;
5242            case 2: return mAnimatorDurationScale;
5243        }
5244        return 0;
5245    }
5246
5247    @Override
5248    public float[] getAnimationScales() {
5249        return new float[] { mWindowAnimationScale, mTransitionAnimationScale,
5250                mAnimatorDurationScale };
5251    }
5252
5253    @Override
5254    public void registerPointerEventListener(PointerEventListener listener) {
5255        mPointerEventDispatcher.registerInputEventListener(listener);
5256    }
5257
5258    @Override
5259    public void unregisterPointerEventListener(PointerEventListener listener) {
5260        mPointerEventDispatcher.unregisterInputEventListener(listener);
5261    }
5262
5263    // Called by window manager policy. Not exposed externally.
5264    @Override
5265    public int getLidState() {
5266        int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY,
5267                InputManagerService.SW_LID);
5268        if (sw > 0) {
5269            // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL.
5270            return LID_CLOSED;
5271        } else if (sw == 0) {
5272            // Switch state: AKEY_STATE_UP.
5273            return LID_OPEN;
5274        } else {
5275            // Switch state: AKEY_STATE_UNKNOWN.
5276            return LID_ABSENT;
5277        }
5278    }
5279
5280    // Called by window manager policy.  Not exposed externally.
5281    @Override
5282    public void switchKeyboardLayout(int deviceId, int direction) {
5283        mInputManager.switchKeyboardLayout(deviceId, direction);
5284    }
5285
5286    // Called by window manager policy.  Not exposed externally.
5287    @Override
5288    public void shutdown(boolean confirm) {
5289        ShutdownThread.shutdown(mContext, confirm);
5290    }
5291
5292    // Called by window manager policy.  Not exposed externally.
5293    @Override
5294    public void rebootSafeMode(boolean confirm) {
5295        ShutdownThread.rebootSafeMode(mContext, confirm);
5296    }
5297
5298    @Override
5299    public void setInputFilter(IInputFilter filter) {
5300        if (!checkCallingPermission(android.Manifest.permission.FILTER_EVENTS, "setInputFilter()")) {
5301            throw new SecurityException("Requires FILTER_EVENTS permission");
5302        }
5303        mInputManager.setInputFilter(filter);
5304    }
5305
5306    @Override
5307    public void setTouchExplorationEnabled(boolean enabled) {
5308        mPolicy.setTouchExplorationEnabled(enabled);
5309    }
5310
5311    public void setCurrentUser(final int newUserId) {
5312        synchronized (mWindowMap) {
5313            int oldUserId = mCurrentUserId;
5314            mCurrentUserId = newUserId;
5315            mAppTransition.setCurrentUser(newUserId);
5316            mPolicy.setCurrentUserLw(newUserId);
5317
5318            // Hide windows that should not be seen by the new user.
5319            final int numDisplays = mDisplayContents.size();
5320            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5321                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
5322                displayContent.switchUserStacks(newUserId);
5323                rebuildAppWindowListLocked(displayContent);
5324            }
5325            performLayoutAndPlaceSurfacesLocked();
5326        }
5327    }
5328
5329    public void enableScreenAfterBoot() {
5330        synchronized(mWindowMap) {
5331            if (DEBUG_BOOT) {
5332                RuntimeException here = new RuntimeException("here");
5333                here.fillInStackTrace();
5334                Slog.i(TAG, "enableScreenAfterBoot: mDisplayEnabled=" + mDisplayEnabled
5335                        + " mForceDisplayEnabled=" + mForceDisplayEnabled
5336                        + " mShowingBootMessages=" + mShowingBootMessages
5337                        + " mSystemBooted=" + mSystemBooted, here);
5338            }
5339            if (mSystemBooted) {
5340                return;
5341            }
5342            mSystemBooted = true;
5343            hideBootMessagesLocked();
5344            // If the screen still doesn't come up after 30 seconds, give
5345            // up and turn it on.
5346            mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30*1000);
5347        }
5348
5349        mPolicy.systemBooted();
5350
5351        performEnableScreen();
5352    }
5353
5354    void enableScreenIfNeededLocked() {
5355        if (DEBUG_BOOT) {
5356            RuntimeException here = new RuntimeException("here");
5357            here.fillInStackTrace();
5358            Slog.i(TAG, "enableScreenIfNeededLocked: mDisplayEnabled=" + mDisplayEnabled
5359                    + " mForceDisplayEnabled=" + mForceDisplayEnabled
5360                    + " mShowingBootMessages=" + mShowingBootMessages
5361                    + " mSystemBooted=" + mSystemBooted, here);
5362        }
5363        if (mDisplayEnabled) {
5364            return;
5365        }
5366        if (!mSystemBooted && !mShowingBootMessages) {
5367            return;
5368        }
5369        mH.sendEmptyMessage(H.ENABLE_SCREEN);
5370    }
5371
5372    public void performBootTimeout() {
5373        synchronized(mWindowMap) {
5374            if (mDisplayEnabled) {
5375                return;
5376            }
5377            Slog.w(TAG, "***** BOOT TIMEOUT: forcing display enabled");
5378            mForceDisplayEnabled = true;
5379        }
5380        performEnableScreen();
5381    }
5382
5383    public void performEnableScreen() {
5384        synchronized(mWindowMap) {
5385            if (DEBUG_BOOT) {
5386                RuntimeException here = new RuntimeException("here");
5387                here.fillInStackTrace();
5388                Slog.i(TAG, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled
5389                        + " mForceDisplayEnabled=" + mForceDisplayEnabled
5390                        + " mShowingBootMessages=" + mShowingBootMessages
5391                        + " mSystemBooted=" + mSystemBooted
5392                        + " mOnlyCore=" + mOnlyCore, here);
5393            }
5394            if (mDisplayEnabled) {
5395                return;
5396            }
5397            if (!mSystemBooted && !mShowingBootMessages) {
5398                return;
5399            }
5400
5401            if (!mForceDisplayEnabled) {
5402                // Don't enable the screen until all existing windows
5403                // have been drawn.
5404                boolean haveBootMsg = false;
5405                boolean haveApp = false;
5406                // if the wallpaper service is disabled on the device, we're never going to have
5407                // wallpaper, don't bother waiting for it
5408                boolean haveWallpaper = false;
5409                boolean wallpaperEnabled = mContext.getResources().getBoolean(
5410                        com.android.internal.R.bool.config_enableWallpaperService)
5411                        && !mOnlyCore;
5412                boolean haveKeyguard = true;
5413                // TODO(multidisplay): Expand to all displays?
5414                final WindowList windows = getDefaultWindowListLocked();
5415                final int N = windows.size();
5416                for (int i=0; i<N; i++) {
5417                    WindowState w = windows.get(i);
5418                    if (w.mAttrs.type == TYPE_KEYGUARD) {
5419                        // Only if there is a keyguard attached to the window manager
5420                        // will we consider ourselves as having a keyguard.  If it
5421                        // isn't attached, we don't know if it wants to be shown or
5422                        // hidden.  If it is attached, we will say we have a keyguard
5423                        // if the window doesn't want to be visible, because in that
5424                        // case it explicitly doesn't want to be shown so we should
5425                        // not delay turning the screen on for it.
5426                        boolean vis = w.mViewVisibility == View.VISIBLE
5427                                && w.mPolicyVisibility;
5428                        haveKeyguard = !vis;
5429                    }
5430                    if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
5431                        return;
5432                    }
5433                    if (w.isDrawnLw()) {
5434                        if (w.mAttrs.type == TYPE_BOOT_PROGRESS) {
5435                            haveBootMsg = true;
5436                        } else if (w.mAttrs.type == TYPE_APPLICATION) {
5437                            haveApp = true;
5438                        } else if (w.mAttrs.type == TYPE_WALLPAPER) {
5439                            haveWallpaper = true;
5440                        } else if (w.mAttrs.type == TYPE_KEYGUARD) {
5441                            haveKeyguard = true;
5442                        }
5443                    }
5444                }
5445
5446                if (DEBUG_SCREEN_ON || DEBUG_BOOT) {
5447                    Slog.i(TAG, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages
5448                            + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp
5449                            + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled
5450                            + " haveKeyguard=" + haveKeyguard);
5451                }
5452
5453                // If we are turning on the screen to show the boot message,
5454                // don't do it until the boot message is actually displayed.
5455                if (!mSystemBooted && !haveBootMsg) {
5456                    return;
5457                }
5458
5459                // If we are turning on the screen after the boot is completed
5460                // normally, don't do so until we have the application and
5461                // wallpaper.
5462                if (mSystemBooted && ((!haveApp && !haveKeyguard) ||
5463                        (wallpaperEnabled && !haveWallpaper))) {
5464                    return;
5465                }
5466            }
5467
5468            mDisplayEnabled = true;
5469            if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG, "******************** ENABLING SCREEN!");
5470            if (false) {
5471                StringWriter sw = new StringWriter();
5472                PrintWriter pw = new FastPrintWriter(sw, false, 1024);
5473                this.dump(null, pw, null);
5474                pw.flush();
5475                Slog.i(TAG, sw.toString());
5476            }
5477            try {
5478                IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
5479                if (surfaceFlinger != null) {
5480                    //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
5481                    Parcel data = Parcel.obtain();
5482                    data.writeInterfaceToken("android.ui.ISurfaceComposer");
5483                    surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
5484                                            data, null, 0);
5485                    data.recycle();
5486                }
5487            } catch (RemoteException ex) {
5488                Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!");
5489            }
5490
5491            // Enable input dispatch.
5492            mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled);
5493        }
5494
5495        mPolicy.enableScreenAfterBoot();
5496
5497        // Make sure the last requested orientation has been applied.
5498        updateRotationUnchecked(false, false);
5499    }
5500
5501    public void showBootMessage(final CharSequence msg, final boolean always) {
5502        boolean first = false;
5503        synchronized(mWindowMap) {
5504            if (DEBUG_BOOT) {
5505                RuntimeException here = new RuntimeException("here");
5506                here.fillInStackTrace();
5507                Slog.i(TAG, "showBootMessage: msg=" + msg + " always=" + always
5508                        + " mAllowBootMessages=" + mAllowBootMessages
5509                        + " mShowingBootMessages=" + mShowingBootMessages
5510                        + " mSystemBooted=" + mSystemBooted, here);
5511            }
5512            if (!mAllowBootMessages) {
5513                return;
5514            }
5515            if (!mShowingBootMessages) {
5516                if (!always) {
5517                    return;
5518                }
5519                first = true;
5520            }
5521            if (mSystemBooted) {
5522                return;
5523            }
5524            mShowingBootMessages = true;
5525            mPolicy.showBootMessage(msg, always);
5526        }
5527        if (first) {
5528            performEnableScreen();
5529        }
5530    }
5531
5532    public void hideBootMessagesLocked() {
5533        if (DEBUG_BOOT) {
5534            RuntimeException here = new RuntimeException("here");
5535            here.fillInStackTrace();
5536            Slog.i(TAG, "hideBootMessagesLocked: mDisplayEnabled=" + mDisplayEnabled
5537                    + " mForceDisplayEnabled=" + mForceDisplayEnabled
5538                    + " mShowingBootMessages=" + mShowingBootMessages
5539                    + " mSystemBooted=" + mSystemBooted, here);
5540        }
5541        if (mShowingBootMessages) {
5542            mShowingBootMessages = false;
5543            mPolicy.hideBootMessages();
5544        }
5545    }
5546
5547    @Override
5548    public void setInTouchMode(boolean mode) {
5549        synchronized(mWindowMap) {
5550            mInTouchMode = mode;
5551        }
5552    }
5553
5554    public void showCircularDisplayMaskIfNeeded() {
5555        if (SystemProperties.getBoolean(SCREEN_CIRCULAR, false)) {
5556            mH.sendMessage(mH.obtainMessage(H.SHOW_DISPLAY_MASK));
5557        }
5558    }
5559
5560    public void showCircularMask() {
5561        synchronized(mWindowMap) {
5562
5563            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5564                    ">>> OPEN TRANSACTION showDisplayMask");
5565            SurfaceControl.openTransaction();
5566            try {
5567                // TODO(multi-display): support multiple displays
5568                if (mCircularDisplayMask == null) {
5569                    mCircularDisplayMask = new CircularDisplayMask(
5570                            getDefaultDisplayContentLocked().getDisplay(),
5571                            mFxSession,
5572                            mPolicy.windowTypeToLayerLw(
5573                                    WindowManager.LayoutParams.TYPE_POINTER)
5574                                    * TYPE_LAYER_MULTIPLIER + 10);
5575                }
5576                mCircularDisplayMask.setVisibility(true);
5577            } finally {
5578                SurfaceControl.closeTransaction();
5579                if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5580                        "<<< CLOSE TRANSACTION showDisplayMask");
5581            }
5582        }
5583    }
5584
5585    // TODO: more accounting of which pid(s) turned it on, keep count,
5586    // only allow disables from pids which have count on, etc.
5587    @Override
5588    public void showStrictModeViolation(boolean on) {
5589        int pid = Binder.getCallingPid();
5590        mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, pid));
5591    }
5592
5593    private void showStrictModeViolation(int arg, int pid) {
5594        final boolean on = arg != 0;
5595        synchronized(mWindowMap) {
5596            // Ignoring requests to enable the red border from clients
5597            // which aren't on screen.  (e.g. Broadcast Receivers in
5598            // the background..)
5599            if (on) {
5600                boolean isVisible = false;
5601                final int numDisplays = mDisplayContents.size();
5602                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5603                    final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
5604                    final int numWindows = windows.size();
5605                    for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
5606                        final WindowState ws = windows.get(winNdx);
5607                        if (ws.mSession.mPid == pid && ws.isVisibleLw()) {
5608                            isVisible = true;
5609                            break;
5610                        }
5611                    }
5612                }
5613                if (!isVisible) {
5614                    return;
5615                }
5616            }
5617
5618            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5619                    ">>> OPEN TRANSACTION showStrictModeViolation");
5620            SurfaceControl.openTransaction();
5621            try {
5622                // TODO(multi-display): support multiple displays
5623                if (mStrictModeFlash == null) {
5624                    mStrictModeFlash = new StrictModeFlash(
5625                            getDefaultDisplayContentLocked().getDisplay(), mFxSession);
5626                }
5627                mStrictModeFlash.setVisibility(on);
5628            } finally {
5629                SurfaceControl.closeTransaction();
5630                if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5631                        "<<< CLOSE TRANSACTION showStrictModeViolation");
5632            }
5633        }
5634    }
5635
5636    @Override
5637    public void setStrictModeVisualIndicatorPreference(String value) {
5638        SystemProperties.set(StrictMode.VISUAL_PROPERTY, value);
5639    }
5640
5641    /**
5642     * Takes a snapshot of the screen.  In landscape mode this grabs the whole screen.
5643     * In portrait mode, it grabs the upper region of the screen based on the vertical dimension
5644     * of the target image.
5645     *
5646     * @param displayId the Display to take a screenshot of.
5647     * @param width the width of the target bitmap
5648     * @param height the height of the target bitmap
5649     * @param force565 if true the returned bitmap will be RGB_565, otherwise it
5650     *                 will be the same config as the surface
5651     */
5652    @Override
5653    public Bitmap screenshotApplications(IBinder appToken, int displayId, int width,
5654            int height, boolean force565) {
5655        if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
5656                "screenshotApplications()")) {
5657            throw new SecurityException("Requires READ_FRAME_BUFFER permission");
5658        }
5659
5660        Bitmap rawss = null;
5661
5662        int maxLayer = 0;
5663        final Rect frame = new Rect();
5664
5665        float scale = 0;
5666        int dw, dh;
5667        int rot = Surface.ROTATION_0;
5668
5669        boolean screenshotReady;
5670        int minLayer;
5671        if (appToken == null) {
5672            screenshotReady = true;
5673            minLayer = 0;
5674        } else {
5675            screenshotReady = false;
5676            minLayer = Integer.MAX_VALUE;
5677        }
5678
5679        int retryCount = 0;
5680        WindowState appWin = null;
5681
5682        do {
5683            if (retryCount++ > 0) {
5684                try {
5685                    Thread.sleep(100);
5686                } catch (InterruptedException e) {
5687                }
5688            }
5689            synchronized(mWindowMap) {
5690                final DisplayContent displayContent = getDisplayContentLocked(displayId);
5691                if (displayContent == null) {
5692                    return null;
5693                }
5694                final DisplayInfo displayInfo = displayContent.getDisplayInfo();
5695                dw = displayInfo.logicalWidth;
5696                dh = displayInfo.logicalHeight;
5697
5698                int aboveAppLayer = mPolicy.windowTypeToLayerLw(TYPE_APPLICATION)
5699                        * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
5700                aboveAppLayer += TYPE_LAYER_MULTIPLIER;
5701
5702                boolean isImeTarget = mInputMethodTarget != null
5703                        && mInputMethodTarget.mAppToken != null
5704                        && mInputMethodTarget.mAppToken.appToken != null
5705                        && mInputMethodTarget.mAppToken.appToken.asBinder() == appToken;
5706
5707                // Figure out the part of the screen that is actually the app.
5708                boolean including = false;
5709                appWin = null;
5710                final WindowList windows = displayContent.getWindowList();
5711                final Rect stackBounds = new Rect();
5712                for (int i = windows.size() - 1; i >= 0; i--) {
5713                    WindowState ws = windows.get(i);
5714                    if (!ws.mHasSurface) {
5715                        continue;
5716                    }
5717                    if (ws.mLayer >= aboveAppLayer) {
5718                        continue;
5719                    }
5720                    // When we will skip windows: when we are not including
5721                    // ones behind a window we didn't skip, and we are actually
5722                    // taking a screenshot of a specific app.
5723                    if (!including && appToken != null) {
5724                        // Also, we can possibly skip this window if it is not
5725                        // an IME target or the application for the screenshot
5726                        // is not the current IME target.
5727                        if (!ws.mIsImWindow || !isImeTarget) {
5728                            // And finally, this window is of no interest if it
5729                            // is not associated with the screenshot app.
5730                            if (ws.mAppToken == null || ws.mAppToken.token != appToken) {
5731                                continue;
5732                            }
5733                            appWin = ws;
5734                            ws.getStackBounds(stackBounds);
5735                        }
5736                    }
5737
5738                    // We keep on including windows until we go past a full-screen
5739                    // window.
5740                    including = !ws.mIsImWindow && !ws.isFullscreen(dw, dh);
5741
5742                    final WindowStateAnimator winAnim = ws.mWinAnimator;
5743                    if (maxLayer < winAnim.mSurfaceLayer) {
5744                        maxLayer = winAnim.mSurfaceLayer;
5745                    }
5746                    if (minLayer > winAnim.mSurfaceLayer) {
5747                        minLayer = winAnim.mSurfaceLayer;
5748                    }
5749
5750                    // Don't include wallpaper in bounds calculation
5751                    if (!ws.mIsWallpaper) {
5752                        final Rect wf = ws.mFrame;
5753                        final Rect cr = ws.mContentInsets;
5754                        int left = wf.left + cr.left;
5755                        int top = wf.top + cr.top;
5756                        int right = wf.right - cr.right;
5757                        int bottom = wf.bottom - cr.bottom;
5758                        frame.union(left, top, right, bottom);
5759                        frame.intersect(stackBounds);
5760                    }
5761
5762                    if (ws.mAppToken != null && ws.mAppToken.token == appToken &&
5763                            ws.isDisplayedLw()) {
5764                        screenshotReady = true;
5765                    }
5766                }
5767
5768                if (appToken != null && appWin == null) {
5769                    // Can't find a window to snapshot.
5770                    if (DEBUG_SCREENSHOT) Slog.i(TAG,
5771                            "Screenshot: Couldn't find a surface matching " + appToken);
5772                    return null;
5773                }
5774                if (!screenshotReady) {
5775                    // Delay and hope that window gets drawn.
5776                    if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot: No image ready for " + appToken
5777                            + ", " + appWin + " drawState=" + appWin.mWinAnimator.mDrawState);
5778                    continue;
5779                }
5780
5781                // Constrain frame to the screen size.
5782                frame.intersect(0, 0, dw, dh);
5783
5784                if (frame.isEmpty() || maxLayer == 0) {
5785                    if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken
5786                            + ": returning null frame=" + frame.toShortString() + " maxLayer="
5787                            + maxLayer);
5788                    return null;
5789                }
5790
5791                // The screenshot API does not apply the current screen rotation.
5792                rot = getDefaultDisplayContentLocked().getDisplay().getRotation();
5793                int fw = frame.width();
5794                int fh = frame.height();
5795
5796                // Constrain thumbnail to smaller of screen width or height. Assumes aspect
5797                // of thumbnail is the same as the screen (in landscape) or square.
5798                scale = Math.max(width / (float) fw, height / (float) fh);
5799                /*
5800                float targetWidthScale = width / (float) fw;
5801                float targetHeightScale = height / (float) fh;
5802                if (fw <= fh) {
5803                    scale = targetWidthScale;
5804                    // If aspect of thumbnail is the same as the screen (in landscape),
5805                    // select the slightly larger value so we fill the entire bitmap
5806                    if (targetHeightScale > scale && (int) (targetHeightScale * fw) == width) {
5807                        scale = targetHeightScale;
5808                    }
5809                } else {
5810                    scale = targetHeightScale;
5811                    // If aspect of thumbnail is the same as the screen (in landscape),
5812                    // select the slightly larger value so we fill the entire bitmap
5813                    if (targetWidthScale > scale && (int) (targetWidthScale * fh) == height) {
5814                        scale = targetWidthScale;
5815                    }
5816                }
5817                */
5818
5819                // The screen shot will contain the entire screen.
5820                dw = (int)(dw*scale);
5821                dh = (int)(dh*scale);
5822                if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
5823                    int tmp = dw;
5824                    dw = dh;
5825                    dh = tmp;
5826                    rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90;
5827                }
5828                if (DEBUG_SCREENSHOT) {
5829                    Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to "
5830                            + maxLayer + " appToken=" + appToken);
5831                    for (int i = 0; i < windows.size(); i++) {
5832                        WindowState win = windows.get(i);
5833                        Slog.i(TAG, win + ": " + win.mLayer
5834                                + " animLayer=" + win.mWinAnimator.mAnimLayer
5835                                + " surfaceLayer=" + win.mWinAnimator.mSurfaceLayer);
5836                    }
5837                }
5838                rawss = SurfaceControl.screenshot(dw, dh, minLayer, maxLayer);
5839            }
5840        } while (!screenshotReady && retryCount <= MAX_SCREENSHOT_RETRIES);
5841        if (retryCount > MAX_SCREENSHOT_RETRIES)  Slog.i(TAG, "Screenshot max retries " +
5842                retryCount + " of " + appToken + " appWin=" + (appWin == null ?
5843                        "null" : (appWin + " drawState=" + appWin.mWinAnimator.mDrawState)));
5844
5845        if (rawss == null) {
5846            Slog.w(TAG, "Screenshot failure taking screenshot for (" + dw + "x" + dh
5847                    + ") to layer " + maxLayer);
5848            return null;
5849        }
5850
5851        Bitmap bm = Bitmap.createBitmap(width, height, force565 ? Config.RGB_565 : rawss.getConfig());
5852        frame.scale(scale);
5853        Matrix matrix = new Matrix();
5854        ScreenRotationAnimation.createRotationMatrix(rot, dw, dh, matrix);
5855        // TODO: Test for RTL vs. LTR and use frame.right-width instead of -frame.left
5856        matrix.postTranslate(-FloatMath.ceil(frame.left), -FloatMath.ceil(frame.top));
5857        Canvas canvas = new Canvas(bm);
5858        canvas.drawColor(0xFF000000);
5859        canvas.drawBitmap(rawss, matrix, null);
5860        canvas.setBitmap(null);
5861
5862        if (DEBUG_SCREENSHOT) {
5863            // TEST IF IT's ALL BLACK
5864            int[] buffer = new int[bm.getWidth() * bm.getHeight()];
5865            bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight());
5866            boolean allBlack = true;
5867            final int firstColor = buffer[0];
5868            for (int i = 0; i < buffer.length; i++) {
5869                if (buffer[i] != firstColor) {
5870                    allBlack = false;
5871                    break;
5872                }
5873            }
5874            if (allBlack) {
5875                Slog.i(TAG, "Screenshot " + appWin + " was monochrome(" +
5876                        Integer.toHexString(firstColor) + ")! mSurfaceLayer=" +
5877                        (appWin != null ? appWin.mWinAnimator.mSurfaceLayer : "null") +
5878                        " minLayer=" + minLayer + " maxLayer=" + maxLayer);
5879            }
5880        }
5881
5882        rawss.recycle();
5883        return bm;
5884    }
5885
5886    /**
5887     * Freeze rotation changes.  (Enable "rotation lock".)
5888     * Persists across reboots.
5889     * @param rotation The desired rotation to freeze to, or -1 to use the
5890     * current rotation.
5891     */
5892    @Override
5893    public void freezeRotation(int rotation) {
5894        if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
5895                "freezeRotation()")) {
5896            throw new SecurityException("Requires SET_ORIENTATION permission");
5897        }
5898        if (rotation < -1 || rotation > Surface.ROTATION_270) {
5899            throw new IllegalArgumentException("Rotation argument must be -1 or a valid "
5900                    + "rotation constant.");
5901        }
5902
5903        if (DEBUG_ORIENTATION) Slog.v(TAG, "freezeRotation: mRotation=" + mRotation);
5904
5905        long origId = Binder.clearCallingIdentity();
5906        try {
5907            mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED,
5908                    rotation == -1 ? mRotation : rotation);
5909        } finally {
5910            Binder.restoreCallingIdentity(origId);
5911        }
5912
5913        updateRotationUnchecked(false, false);
5914    }
5915
5916    /**
5917     * Thaw rotation changes.  (Disable "rotation lock".)
5918     * Persists across reboots.
5919     */
5920    @Override
5921    public void thawRotation() {
5922        if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
5923                "thawRotation()")) {
5924            throw new SecurityException("Requires SET_ORIENTATION permission");
5925        }
5926
5927        if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation);
5928
5929        long origId = Binder.clearCallingIdentity();
5930        try {
5931            mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE,
5932                    777); // rot not used
5933        } finally {
5934            Binder.restoreCallingIdentity(origId);
5935        }
5936
5937        updateRotationUnchecked(false, false);
5938    }
5939
5940    /**
5941     * Recalculate the current rotation.
5942     *
5943     * Called by the window manager policy whenever the state of the system changes
5944     * such that the current rotation might need to be updated, such as when the
5945     * device is docked or rotated into a new posture.
5946     */
5947    @Override
5948    public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
5949        updateRotationUnchecked(alwaysSendConfiguration, forceRelayout);
5950    }
5951
5952    /**
5953     * Temporarily pauses rotation changes until resumed.
5954     *
5955     * This can be used to prevent rotation changes from occurring while the user is
5956     * performing certain operations, such as drag and drop.
5957     *
5958     * This call nests and must be matched by an equal number of calls to
5959     * {@link #resumeRotationLocked}.
5960     */
5961    void pauseRotationLocked() {
5962        mDeferredRotationPauseCount += 1;
5963    }
5964
5965    /**
5966     * Resumes normal rotation changes after being paused.
5967     */
5968    void resumeRotationLocked() {
5969        if (mDeferredRotationPauseCount > 0) {
5970            mDeferredRotationPauseCount -= 1;
5971            if (mDeferredRotationPauseCount == 0) {
5972                boolean changed = updateRotationUncheckedLocked(false);
5973                if (changed) {
5974                    mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
5975                }
5976            }
5977        }
5978    }
5979
5980    public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) {
5981        if(DEBUG_ORIENTATION) Slog.v(TAG, "updateRotationUnchecked("
5982                   + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")");
5983
5984        long origId = Binder.clearCallingIdentity();
5985        boolean changed;
5986        synchronized(mWindowMap) {
5987            changed = updateRotationUncheckedLocked(false);
5988            if (!changed || forceRelayout) {
5989                getDefaultDisplayContentLocked().layoutNeeded = true;
5990                performLayoutAndPlaceSurfacesLocked();
5991            }
5992        }
5993
5994        if (changed || alwaysSendConfiguration) {
5995            sendNewConfiguration();
5996        }
5997
5998        Binder.restoreCallingIdentity(origId);
5999    }
6000
6001    // TODO(multidisplay): Rotate any display?
6002    /**
6003     * Updates the current rotation.
6004     *
6005     * Returns true if the rotation has been changed.  In this case YOU
6006     * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN.
6007     */
6008    public boolean updateRotationUncheckedLocked(boolean inTransaction) {
6009        if (mDeferredRotationPauseCount > 0) {
6010            // Rotation updates have been paused temporarily.  Defer the update until
6011            // updates have been resumed.
6012            if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, rotation is paused.");
6013            return false;
6014        }
6015
6016        ScreenRotationAnimation screenRotationAnimation =
6017                mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
6018        if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
6019            // Rotation updates cannot be performed while the previous rotation change
6020            // animation is still in progress.  Skip this update.  We will try updating
6021            // again after the animation is finished and the display is unfrozen.
6022            if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, animation in progress.");
6023            return false;
6024        }
6025
6026        if (!mDisplayEnabled) {
6027            // No point choosing a rotation if the display is not enabled.
6028            if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, display is not enabled.");
6029            return false;
6030        }
6031
6032        // TODO: Implement forced rotation changes.
6033        //       Set mAltOrientation to indicate that the application is receiving
6034        //       an orientation that has different metrics than it expected.
6035        //       eg. Portrait instead of Landscape.
6036
6037        int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation);
6038        boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw(
6039                mForcedAppOrientation, rotation);
6040
6041        if (DEBUG_ORIENTATION) {
6042            Slog.v(TAG, "Application requested orientation "
6043                    + mForcedAppOrientation + ", got rotation " + rotation
6044                    + " which has " + (altOrientation ? "incompatible" : "compatible")
6045                    + " metrics");
6046        }
6047
6048        if (mRotation == rotation && mAltOrientation == altOrientation) {
6049            // No change.
6050            return false;
6051        }
6052
6053        if (DEBUG_ORIENTATION) {
6054            Slog.v(TAG,
6055                "Rotation changed to " + rotation + (altOrientation ? " (alt)" : "")
6056                + " from " + mRotation + (mAltOrientation ? " (alt)" : "")
6057                + ", forceApp=" + mForcedAppOrientation);
6058        }
6059
6060        mRotation = rotation;
6061        mAltOrientation = altOrientation;
6062        mPolicy.setRotationLw(mRotation);
6063
6064        mWindowsFreezingScreen = true;
6065        mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
6066        mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION);
6067        mWaitingForConfig = true;
6068        final DisplayContent displayContent = getDefaultDisplayContentLocked();
6069        displayContent.layoutNeeded = true;
6070        final int[] anim = new int[2];
6071        if (displayContent.isDimming()) {
6072            anim[0] = anim[1] = 0;
6073        } else {
6074            mPolicy.selectRotationAnimationLw(anim);
6075        }
6076        startFreezingDisplayLocked(inTransaction, anim[0], anim[1]);
6077        // startFreezingDisplayLocked can reset the ScreenRotationAnimation.
6078        screenRotationAnimation =
6079                mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
6080
6081        // We need to update our screen size information to match the new
6082        // rotation.  Note that this is redundant with the later call to
6083        // sendNewConfiguration() that must be called after this function
6084        // returns...  however we need to do the screen size part of that
6085        // before then so we have the correct size to use when initializing
6086        // the rotation animation for the new rotation.
6087        computeScreenConfigurationLocked(null);
6088
6089        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
6090        if (!inTransaction) {
6091            if (SHOW_TRANSACTIONS) {
6092                Slog.i(TAG, ">>> OPEN TRANSACTION setRotationUnchecked");
6093            }
6094            SurfaceControl.openTransaction();
6095        }
6096        try {
6097            // NOTE: We disable the rotation in the emulator because
6098            //       it doesn't support hardware OpenGL emulation yet.
6099            if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
6100                    && screenRotationAnimation.hasScreenshot()) {
6101                if (screenRotationAnimation.setRotationInTransaction(
6102                        rotation, mFxSession,
6103                        MAX_ANIMATION_DURATION, mTransitionAnimationScale,
6104                        displayInfo.logicalWidth, displayInfo.logicalHeight)) {
6105                    scheduleAnimationLocked();
6106                }
6107            }
6108
6109            mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
6110        } finally {
6111            if (!inTransaction) {
6112                SurfaceControl.closeTransaction();
6113                if (SHOW_LIGHT_TRANSACTIONS) {
6114                    Slog.i(TAG, "<<< CLOSE TRANSACTION setRotationUnchecked");
6115                }
6116            }
6117        }
6118
6119        final WindowList windows = displayContent.getWindowList();
6120        for (int i = windows.size() - 1; i >= 0; i--) {
6121            WindowState w = windows.get(i);
6122            if (w.mHasSurface) {
6123                if (DEBUG_ORIENTATION) Slog.v(TAG, "Set mOrientationChanging of " + w);
6124                w.mOrientationChanging = true;
6125                mInnerFields.mOrientationChangeComplete = false;
6126            }
6127            w.mLastFreezeDuration = 0;
6128        }
6129
6130        for (int i=mRotationWatchers.size()-1; i>=0; i--) {
6131            try {
6132                mRotationWatchers.get(i).watcher.onRotationChanged(rotation);
6133            } catch (RemoteException e) {
6134            }
6135        }
6136
6137        //TODO (multidisplay): Magnification is supported only for the default display.
6138        if (mDisplayMagnifier != null
6139                && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) {
6140            mDisplayMagnifier.onRotationChangedLocked(getDefaultDisplayContentLocked(), rotation);
6141        }
6142
6143        return true;
6144    }
6145
6146    @Override
6147    public int getRotation() {
6148        return mRotation;
6149    }
6150
6151    @Override
6152    public boolean isRotationFrozen() {
6153        return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED;
6154    }
6155
6156    @Override
6157    public int watchRotation(IRotationWatcher watcher) {
6158        final IBinder watcherBinder = watcher.asBinder();
6159        IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
6160            @Override
6161            public void binderDied() {
6162                synchronized (mWindowMap) {
6163                    for (int i=0; i<mRotationWatchers.size(); i++) {
6164                        if (watcherBinder == mRotationWatchers.get(i).watcher.asBinder()) {
6165                            RotationWatcher removed = mRotationWatchers.remove(i);
6166                            if (removed != null) {
6167                                removed.watcher.asBinder().unlinkToDeath(this, 0);
6168                            }
6169                            i--;
6170                        }
6171                    }
6172                }
6173            }
6174        };
6175
6176        synchronized (mWindowMap) {
6177            try {
6178                watcher.asBinder().linkToDeath(dr, 0);
6179                mRotationWatchers.add(new RotationWatcher(watcher, dr));
6180            } catch (RemoteException e) {
6181                // Client died, no cleanup needed.
6182            }
6183
6184            return mRotation;
6185        }
6186    }
6187
6188    @Override
6189    public void removeRotationWatcher(IRotationWatcher watcher) {
6190        final IBinder watcherBinder = watcher.asBinder();
6191        synchronized (mWindowMap) {
6192            for (int i=0; i<mRotationWatchers.size(); i++) {
6193                RotationWatcher rotationWatcher = mRotationWatchers.get(i);
6194                if (watcherBinder == rotationWatcher.watcher.asBinder()) {
6195                    RotationWatcher removed = mRotationWatchers.remove(i);
6196                    if (removed != null) {
6197                        removed.watcher.asBinder().unlinkToDeath(removed.dr, 0);
6198                        i--;
6199                    }
6200                }
6201            }
6202        }
6203    }
6204
6205    /**
6206     * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact
6207     * theme attribute) on devices that feature a physical options menu key attempt to position
6208     * their menu panel window along the edge of the screen nearest the physical menu key.
6209     * This lowers the travel distance between invoking the menu panel and selecting
6210     * a menu option.
6211     *
6212     * This method helps control where that menu is placed. Its current implementation makes
6213     * assumptions about the menu key and its relationship to the screen based on whether
6214     * the device's natural orientation is portrait (width < height) or landscape.
6215     *
6216     * The menu key is assumed to be located along the bottom edge of natural-portrait
6217     * devices and along the right edge of natural-landscape devices. If these assumptions
6218     * do not hold for the target device, this method should be changed to reflect that.
6219     *
6220     * @return A {@link Gravity} value for placing the options menu window
6221     */
6222    @Override
6223    public int getPreferredOptionsPanelGravity() {
6224        synchronized (mWindowMap) {
6225            final int rotation = getRotation();
6226
6227            // TODO(multidisplay): Assume that such devices physical keys are on the main screen.
6228            final DisplayContent displayContent = getDefaultDisplayContentLocked();
6229            if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) {
6230                // On devices with a natural orientation of portrait
6231                switch (rotation) {
6232                    default:
6233                    case Surface.ROTATION_0:
6234                        return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6235                    case Surface.ROTATION_90:
6236                        return Gravity.RIGHT | Gravity.BOTTOM;
6237                    case Surface.ROTATION_180:
6238                        return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6239                    case Surface.ROTATION_270:
6240                        return Gravity.START | Gravity.BOTTOM;
6241                }
6242            }
6243
6244            // On devices with a natural orientation of landscape
6245            switch (rotation) {
6246                default:
6247                case Surface.ROTATION_0:
6248                    return Gravity.RIGHT | Gravity.BOTTOM;
6249                case Surface.ROTATION_90:
6250                    return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6251                case Surface.ROTATION_180:
6252                    return Gravity.START | Gravity.BOTTOM;
6253                case Surface.ROTATION_270:
6254                    return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6255            }
6256        }
6257    }
6258
6259    /**
6260     * Starts the view server on the specified port.
6261     *
6262     * @param port The port to listener to.
6263     *
6264     * @return True if the server was successfully started, false otherwise.
6265     *
6266     * @see com.android.server.wm.ViewServer
6267     * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT
6268     */
6269    @Override
6270    public boolean startViewServer(int port) {
6271        if (isSystemSecure()) {
6272            return false;
6273        }
6274
6275        if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) {
6276            return false;
6277        }
6278
6279        if (port < 1024) {
6280            return false;
6281        }
6282
6283        if (mViewServer != null) {
6284            if (!mViewServer.isRunning()) {
6285                try {
6286                    return mViewServer.start();
6287                } catch (IOException e) {
6288                    Slog.w(TAG, "View server did not start");
6289                }
6290            }
6291            return false;
6292        }
6293
6294        try {
6295            mViewServer = new ViewServer(this, port);
6296            return mViewServer.start();
6297        } catch (IOException e) {
6298            Slog.w(TAG, "View server did not start");
6299        }
6300        return false;
6301    }
6302
6303    private boolean isSystemSecure() {
6304        return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) &&
6305                "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
6306    }
6307
6308    /**
6309     * Stops the view server if it exists.
6310     *
6311     * @return True if the server stopped, false if it wasn't started or
6312     *         couldn't be stopped.
6313     *
6314     * @see com.android.server.wm.ViewServer
6315     */
6316    @Override
6317    public boolean stopViewServer() {
6318        if (isSystemSecure()) {
6319            return false;
6320        }
6321
6322        if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) {
6323            return false;
6324        }
6325
6326        if (mViewServer != null) {
6327            return mViewServer.stop();
6328        }
6329        return false;
6330    }
6331
6332    /**
6333     * Indicates whether the view server is running.
6334     *
6335     * @return True if the server is running, false otherwise.
6336     *
6337     * @see com.android.server.wm.ViewServer
6338     */
6339    @Override
6340    public boolean isViewServerRunning() {
6341        if (isSystemSecure()) {
6342            return false;
6343        }
6344
6345        if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) {
6346            return false;
6347        }
6348
6349        return mViewServer != null && mViewServer.isRunning();
6350    }
6351
6352    /**
6353     * Lists all availble windows in the system. The listing is written in the
6354     * specified Socket's output stream with the following syntax:
6355     * windowHashCodeInHexadecimal windowName
6356     * Each line of the ouput represents a different window.
6357     *
6358     * @param client The remote client to send the listing to.
6359     * @return False if an error occured, true otherwise.
6360     */
6361    boolean viewServerListWindows(Socket client) {
6362        if (isSystemSecure()) {
6363            return false;
6364        }
6365
6366        boolean result = true;
6367
6368        WindowList windows = new WindowList();
6369        synchronized (mWindowMap) {
6370            //noinspection unchecked
6371            final int numDisplays = mDisplayContents.size();
6372            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
6373                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
6374                windows.addAll(displayContent.getWindowList());
6375            }
6376        }
6377
6378        BufferedWriter out = null;
6379
6380        // Any uncaught exception will crash the system process
6381        try {
6382            OutputStream clientStream = client.getOutputStream();
6383            out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
6384
6385            final int count = windows.size();
6386            for (int i = 0; i < count; i++) {
6387                final WindowState w = windows.get(i);
6388                out.write(Integer.toHexString(System.identityHashCode(w)));
6389                out.write(' ');
6390                out.append(w.mAttrs.getTitle());
6391                out.write('\n');
6392            }
6393
6394            out.write("DONE.\n");
6395            out.flush();
6396        } catch (Exception e) {
6397            result = false;
6398        } finally {
6399            if (out != null) {
6400                try {
6401                    out.close();
6402                } catch (IOException e) {
6403                    result = false;
6404                }
6405            }
6406        }
6407
6408        return result;
6409    }
6410
6411    // TODO(multidisplay): Extend to multiple displays.
6412    /**
6413     * Returns the focused window in the following format:
6414     * windowHashCodeInHexadecimal windowName
6415     *
6416     * @param client The remote client to send the listing to.
6417     * @return False if an error occurred, true otherwise.
6418     */
6419    boolean viewServerGetFocusedWindow(Socket client) {
6420        if (isSystemSecure()) {
6421            return false;
6422        }
6423
6424        boolean result = true;
6425
6426        WindowState focusedWindow = getFocusedWindow();
6427
6428        BufferedWriter out = null;
6429
6430        // Any uncaught exception will crash the system process
6431        try {
6432            OutputStream clientStream = client.getOutputStream();
6433            out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
6434
6435            if(focusedWindow != null) {
6436                out.write(Integer.toHexString(System.identityHashCode(focusedWindow)));
6437                out.write(' ');
6438                out.append(focusedWindow.mAttrs.getTitle());
6439            }
6440            out.write('\n');
6441            out.flush();
6442        } catch (Exception e) {
6443            result = false;
6444        } finally {
6445            if (out != null) {
6446                try {
6447                    out.close();
6448                } catch (IOException e) {
6449                    result = false;
6450                }
6451            }
6452        }
6453
6454        return result;
6455    }
6456
6457    /**
6458     * Sends a command to a target window. The result of the command, if any, will be
6459     * written in the output stream of the specified socket.
6460     *
6461     * The parameters must follow this syntax:
6462     * windowHashcode extra
6463     *
6464     * Where XX is the length in characeters of the windowTitle.
6465     *
6466     * The first parameter is the target window. The window with the specified hashcode
6467     * will be the target. If no target can be found, nothing happens. The extra parameters
6468     * will be delivered to the target window and as parameters to the command itself.
6469     *
6470     * @param client The remote client to sent the result, if any, to.
6471     * @param command The command to execute.
6472     * @param parameters The command parameters.
6473     *
6474     * @return True if the command was successfully delivered, false otherwise. This does
6475     *         not indicate whether the command itself was successful.
6476     */
6477    boolean viewServerWindowCommand(Socket client, String command, String parameters) {
6478        if (isSystemSecure()) {
6479            return false;
6480        }
6481
6482        boolean success = true;
6483        Parcel data = null;
6484        Parcel reply = null;
6485
6486        BufferedWriter out = null;
6487
6488        // Any uncaught exception will crash the system process
6489        try {
6490            // Find the hashcode of the window
6491            int index = parameters.indexOf(' ');
6492            if (index == -1) {
6493                index = parameters.length();
6494            }
6495            final String code = parameters.substring(0, index);
6496            int hashCode = (int) Long.parseLong(code, 16);
6497
6498            // Extract the command's parameter after the window description
6499            if (index < parameters.length()) {
6500                parameters = parameters.substring(index + 1);
6501            } else {
6502                parameters = "";
6503            }
6504
6505            final WindowState window = findWindow(hashCode);
6506            if (window == null) {
6507                return false;
6508            }
6509
6510            data = Parcel.obtain();
6511            data.writeInterfaceToken("android.view.IWindow");
6512            data.writeString(command);
6513            data.writeString(parameters);
6514            data.writeInt(1);
6515            ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0);
6516
6517            reply = Parcel.obtain();
6518
6519            final IBinder binder = window.mClient.asBinder();
6520            // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER
6521            binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
6522
6523            reply.readException();
6524
6525            if (!client.isOutputShutdown()) {
6526                out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
6527                out.write("DONE\n");
6528                out.flush();
6529            }
6530
6531        } catch (Exception e) {
6532            Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e);
6533            success = false;
6534        } finally {
6535            if (data != null) {
6536                data.recycle();
6537            }
6538            if (reply != null) {
6539                reply.recycle();
6540            }
6541            if (out != null) {
6542                try {
6543                    out.close();
6544                } catch (IOException e) {
6545
6546                }
6547            }
6548        }
6549
6550        return success;
6551    }
6552
6553    public void addWindowChangeListener(WindowChangeListener listener) {
6554        synchronized(mWindowMap) {
6555            mWindowChangeListeners.add(listener);
6556        }
6557    }
6558
6559    public void removeWindowChangeListener(WindowChangeListener listener) {
6560        synchronized(mWindowMap) {
6561            mWindowChangeListeners.remove(listener);
6562        }
6563    }
6564
6565    private void notifyWindowsChanged() {
6566        WindowChangeListener[] windowChangeListeners;
6567        synchronized(mWindowMap) {
6568            if(mWindowChangeListeners.isEmpty()) {
6569                return;
6570            }
6571            windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
6572            windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
6573        }
6574        int N = windowChangeListeners.length;
6575        for(int i = 0; i < N; i++) {
6576            windowChangeListeners[i].windowsChanged();
6577        }
6578    }
6579
6580    private void notifyFocusChanged() {
6581        WindowChangeListener[] windowChangeListeners;
6582        synchronized(mWindowMap) {
6583            if(mWindowChangeListeners.isEmpty()) {
6584                return;
6585            }
6586            windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
6587            windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
6588        }
6589        int N = windowChangeListeners.length;
6590        for(int i = 0; i < N; i++) {
6591            windowChangeListeners[i].focusChanged();
6592        }
6593    }
6594
6595    private WindowState findWindow(int hashCode) {
6596        if (hashCode == -1) {
6597            // TODO(multidisplay): Extend to multiple displays.
6598            return getFocusedWindow();
6599        }
6600
6601        synchronized (mWindowMap) {
6602            final int numDisplays = mDisplayContents.size();
6603            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
6604                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
6605                final int numWindows = windows.size();
6606                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
6607                    final WindowState w = windows.get(winNdx);
6608                    if (System.identityHashCode(w) == hashCode) {
6609                        return w;
6610                    }
6611                }
6612            }
6613        }
6614
6615        return null;
6616    }
6617
6618    /*
6619     * Instruct the Activity Manager to fetch the current configuration and broadcast
6620     * that to config-changed listeners if appropriate.
6621     */
6622    void sendNewConfiguration() {
6623        try {
6624            mActivityManager.updateConfiguration(null);
6625        } catch (RemoteException e) {
6626        }
6627    }
6628
6629    public Configuration computeNewConfiguration() {
6630        synchronized (mWindowMap) {
6631            Configuration config = computeNewConfigurationLocked();
6632            if (config == null && mWaitingForConfig) {
6633                // Nothing changed but we are waiting for something... stop that!
6634                mWaitingForConfig = false;
6635                mLastFinishedFreezeSource = "new-config";
6636                performLayoutAndPlaceSurfacesLocked();
6637            }
6638            return config;
6639        }
6640    }
6641
6642    Configuration computeNewConfigurationLocked() {
6643        Configuration config = new Configuration();
6644        config.fontScale = 0;
6645        if (!computeScreenConfigurationLocked(config)) {
6646            return null;
6647        }
6648        return config;
6649    }
6650
6651    private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int dw, int dh) {
6652        // TODO: Multidisplay: for now only use with default display.
6653        final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation);
6654        if (width < displayInfo.smallestNominalAppWidth) {
6655            displayInfo.smallestNominalAppWidth = width;
6656        }
6657        if (width > displayInfo.largestNominalAppWidth) {
6658            displayInfo.largestNominalAppWidth = width;
6659        }
6660        final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation);
6661        if (height < displayInfo.smallestNominalAppHeight) {
6662            displayInfo.smallestNominalAppHeight = height;
6663        }
6664        if (height > displayInfo.largestNominalAppHeight) {
6665            displayInfo.largestNominalAppHeight = height;
6666        }
6667    }
6668
6669    private int reduceConfigLayout(int curLayout, int rotation, float density,
6670            int dw, int dh) {
6671        // TODO: Multidisplay: for now only use with default display.
6672        // Get the app screen size at this rotation.
6673        int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation);
6674        int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation);
6675
6676        // Compute the screen layout size class for this rotation.
6677        int longSize = w;
6678        int shortSize = h;
6679        if (longSize < shortSize) {
6680            int tmp = longSize;
6681            longSize = shortSize;
6682            shortSize = tmp;
6683        }
6684        longSize = (int)(longSize/density);
6685        shortSize = (int)(shortSize/density);
6686        return Configuration.reduceScreenLayout(curLayout, longSize, shortSize);
6687    }
6688
6689    private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated,
6690                  int dw, int dh, float density, Configuration outConfig) {
6691        // TODO: Multidisplay: for now only use with default display.
6692
6693        // We need to determine the smallest width that will occur under normal
6694        // operation.  To this, start with the base screen size and compute the
6695        // width under the different possible rotations.  We need to un-rotate
6696        // the current screen dimensions before doing this.
6697        int unrotDw, unrotDh;
6698        if (rotated) {
6699            unrotDw = dh;
6700            unrotDh = dw;
6701        } else {
6702            unrotDw = dw;
6703            unrotDh = dh;
6704        }
6705        displayInfo.smallestNominalAppWidth = 1<<30;
6706        displayInfo.smallestNominalAppHeight = 1<<30;
6707        displayInfo.largestNominalAppWidth = 0;
6708        displayInfo.largestNominalAppHeight = 0;
6709        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, unrotDw, unrotDh);
6710        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, unrotDh, unrotDw);
6711        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, unrotDw, unrotDh);
6712        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, unrotDh, unrotDw);
6713        int sl = Configuration.resetScreenLayout(outConfig.screenLayout);
6714        sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh);
6715        sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw);
6716        sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh);
6717        sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw);
6718        outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density);
6719        outConfig.screenLayout = sl;
6720    }
6721
6722    private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm,
6723            int dw, int dh) {
6724        // TODO: Multidisplay: for now only use with default display.
6725        dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation);
6726        dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation);
6727        float scale = CompatibilityInfo.computeCompatibleScaling(dm, null);
6728        int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f);
6729        if (curSize == 0 || size < curSize) {
6730            curSize = size;
6731        }
6732        return curSize;
6733    }
6734
6735    private int computeCompatSmallestWidth(boolean rotated, DisplayMetrics dm, int dw, int dh) {
6736        // TODO: Multidisplay: for now only use with default display.
6737        mTmpDisplayMetrics.setTo(dm);
6738        final DisplayMetrics tmpDm = mTmpDisplayMetrics;
6739        final int unrotDw, unrotDh;
6740        if (rotated) {
6741            unrotDw = dh;
6742            unrotDh = dw;
6743        } else {
6744            unrotDw = dw;
6745            unrotDh = dh;
6746        }
6747        int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, tmpDm, unrotDw, unrotDh);
6748        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, tmpDm, unrotDh, unrotDw);
6749        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, tmpDm, unrotDw, unrotDh);
6750        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, tmpDm, unrotDh, unrotDw);
6751        return sw;
6752    }
6753
6754    boolean computeScreenConfigurationLocked(Configuration config) {
6755        if (!mDisplayReady) {
6756            return false;
6757        }
6758
6759        // TODO(multidisplay): For now, apply Configuration to main screen only.
6760        final DisplayContent displayContent = getDefaultDisplayContentLocked();
6761
6762        // Use the effective "visual" dimensions based on current rotation
6763        final boolean rotated = (mRotation == Surface.ROTATION_90
6764                || mRotation == Surface.ROTATION_270);
6765        final int realdw = rotated ?
6766                displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth;
6767        final int realdh = rotated ?
6768                displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight;
6769        int dw = realdw;
6770        int dh = realdh;
6771
6772        if (mAltOrientation) {
6773            if (realdw > realdh) {
6774                // Turn landscape into portrait.
6775                int maxw = (int)(realdh/1.3f);
6776                if (maxw < realdw) {
6777                    dw = maxw;
6778                }
6779            } else {
6780                // Turn portrait into landscape.
6781                int maxh = (int)(realdw/1.3f);
6782                if (maxh < realdh) {
6783                    dh = maxh;
6784                }
6785            }
6786        }
6787
6788        if (config != null) {
6789            config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT :
6790                    Configuration.ORIENTATION_LANDSCAPE;
6791        }
6792
6793        // Update application display metrics.
6794        final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation);
6795        final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation);
6796        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
6797        synchronized(displayContent.mDisplaySizeLock) {
6798            displayInfo.rotation = mRotation;
6799            displayInfo.logicalWidth = dw;
6800            displayInfo.logicalHeight = dh;
6801            displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity;
6802            displayInfo.appWidth = appWidth;
6803            displayInfo.appHeight = appHeight;
6804            displayInfo.getLogicalMetrics(mRealDisplayMetrics,
6805                    CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
6806            displayInfo.getAppMetrics(mDisplayMetrics);
6807            mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
6808                    displayContent.getDisplayId(), displayInfo);
6809        }
6810        if (false) {
6811            Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight);
6812        }
6813
6814        final DisplayMetrics dm = mDisplayMetrics;
6815        mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm,
6816                mCompatDisplayMetrics);
6817
6818        if (config != null) {
6819            config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation)
6820                    / dm.density);
6821            config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation)
6822                    / dm.density);
6823            computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, dm.density, config);
6824
6825            config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale);
6826            config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale);
6827            config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh);
6828            config.densityDpi = displayContent.mBaseDisplayDensity;
6829
6830            // Update the configuration based on available input devices, lid switch,
6831            // and platform configuration.
6832            config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
6833            config.keyboard = Configuration.KEYBOARD_NOKEYS;
6834            config.navigation = Configuration.NAVIGATION_NONAV;
6835
6836            int keyboardPresence = 0;
6837            int navigationPresence = 0;
6838            final InputDevice[] devices = mInputManager.getInputDevices();
6839            final int len = devices.length;
6840            for (int i = 0; i < len; i++) {
6841                InputDevice device = devices[i];
6842                if (!device.isVirtual()) {
6843                    final int sources = device.getSources();
6844                    final int presenceFlag = device.isExternal() ?
6845                            WindowManagerPolicy.PRESENCE_EXTERNAL :
6846                                    WindowManagerPolicy.PRESENCE_INTERNAL;
6847
6848                    if (mIsTouchDevice) {
6849                        if ((sources & InputDevice.SOURCE_TOUCHSCREEN) ==
6850                                InputDevice.SOURCE_TOUCHSCREEN) {
6851                            config.touchscreen = Configuration.TOUCHSCREEN_FINGER;
6852                        }
6853                    } else {
6854                        config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
6855                    }
6856
6857                    if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) {
6858                        config.navigation = Configuration.NAVIGATION_TRACKBALL;
6859                        navigationPresence |= presenceFlag;
6860                    } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD
6861                            && config.navigation == Configuration.NAVIGATION_NONAV) {
6862                        config.navigation = Configuration.NAVIGATION_DPAD;
6863                        navigationPresence |= presenceFlag;
6864                    }
6865
6866                    if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {
6867                        config.keyboard = Configuration.KEYBOARD_QWERTY;
6868                        keyboardPresence |= presenceFlag;
6869                    }
6870                }
6871            }
6872
6873            // Determine whether a hard keyboard is available and enabled.
6874            boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS;
6875            if (hardKeyboardAvailable != mHardKeyboardAvailable) {
6876                mHardKeyboardAvailable = hardKeyboardAvailable;
6877                mHardKeyboardEnabled = hardKeyboardAvailable;
6878                mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
6879                mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
6880            }
6881            if (!mHardKeyboardEnabled) {
6882                config.keyboard = Configuration.KEYBOARD_NOKEYS;
6883            }
6884
6885            // Let the policy update hidden states.
6886            config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
6887            config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
6888            config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO;
6889            mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence);
6890        }
6891
6892        return true;
6893    }
6894
6895    public boolean isHardKeyboardAvailable() {
6896        synchronized (mWindowMap) {
6897            return mHardKeyboardAvailable;
6898        }
6899    }
6900
6901    public boolean isHardKeyboardEnabled() {
6902        synchronized (mWindowMap) {
6903            return mHardKeyboardEnabled;
6904        }
6905    }
6906
6907    public void setHardKeyboardEnabled(boolean enabled) {
6908        synchronized (mWindowMap) {
6909            if (mHardKeyboardEnabled != enabled) {
6910                mHardKeyboardEnabled = enabled;
6911                mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
6912            }
6913        }
6914    }
6915
6916    public void setOnHardKeyboardStatusChangeListener(
6917            OnHardKeyboardStatusChangeListener listener) {
6918        synchronized (mWindowMap) {
6919            mHardKeyboardStatusChangeListener = listener;
6920        }
6921    }
6922
6923    void notifyHardKeyboardStatusChange() {
6924        final boolean available, enabled;
6925        final OnHardKeyboardStatusChangeListener listener;
6926        synchronized (mWindowMap) {
6927            listener = mHardKeyboardStatusChangeListener;
6928            available = mHardKeyboardAvailable;
6929            enabled = mHardKeyboardEnabled;
6930        }
6931        if (listener != null) {
6932            listener.onHardKeyboardStatusChange(available, enabled);
6933        }
6934    }
6935
6936    // -------------------------------------------------------------
6937    // Drag and drop
6938    // -------------------------------------------------------------
6939
6940    IBinder prepareDragSurface(IWindow window, SurfaceSession session,
6941            int flags, int width, int height, Surface outSurface) {
6942        if (DEBUG_DRAG) {
6943            Slog.d(TAG, "prepare drag surface: w=" + width + " h=" + height
6944                    + " flags=" + Integer.toHexString(flags) + " win=" + window
6945                    + " asbinder=" + window.asBinder());
6946        }
6947
6948        final int callerPid = Binder.getCallingPid();
6949        final long origId = Binder.clearCallingIdentity();
6950        IBinder token = null;
6951
6952        try {
6953            synchronized (mWindowMap) {
6954                try {
6955                    if (mDragState == null) {
6956                        // TODO(multi-display): support other displays
6957                        final DisplayContent displayContent = getDefaultDisplayContentLocked();
6958                        final Display display = displayContent.getDisplay();
6959                        SurfaceControl surface = new SurfaceControl(session, "drag surface",
6960                                width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
6961                        surface.setLayerStack(display.getLayerStack());
6962                        if (SHOW_TRANSACTIONS) Slog.i(TAG, "  DRAG "
6963                                + surface + ": CREATE");
6964                        outSurface.copyFrom(surface);
6965                        final IBinder winBinder = window.asBinder();
6966                        token = new Binder();
6967                        mDragState = new DragState(this, token, surface, /*flags*/ 0, winBinder);
6968                        token = mDragState.mToken = new Binder();
6969
6970                        // 5 second timeout for this window to actually begin the drag
6971                        mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder);
6972                        Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder);
6973                        mH.sendMessageDelayed(msg, 5000);
6974                    } else {
6975                        Slog.w(TAG, "Drag already in progress");
6976                    }
6977                } catch (OutOfResourcesException e) {
6978                    Slog.e(TAG, "Can't allocate drag surface w=" + width + " h=" + height, e);
6979                    if (mDragState != null) {
6980                        mDragState.reset();
6981                        mDragState = null;
6982                    }
6983                }
6984            }
6985        } finally {
6986            Binder.restoreCallingIdentity(origId);
6987        }
6988
6989        return token;
6990    }
6991
6992    // -------------------------------------------------------------
6993    // Input Events and Focus Management
6994    // -------------------------------------------------------------
6995
6996    final InputMonitor mInputMonitor = new InputMonitor(this);
6997    private boolean mEventDispatchingEnabled;
6998
6999    @Override
7000    public void pauseKeyDispatching(IBinder _token) {
7001        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
7002                "pauseKeyDispatching()")) {
7003            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
7004        }
7005
7006        synchronized (mWindowMap) {
7007            WindowToken token = mTokenMap.get(_token);
7008            if (token != null) {
7009                mInputMonitor.pauseDispatchingLw(token);
7010            }
7011        }
7012    }
7013
7014    @Override
7015    public void resumeKeyDispatching(IBinder _token) {
7016        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
7017                "resumeKeyDispatching()")) {
7018            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
7019        }
7020
7021        synchronized (mWindowMap) {
7022            WindowToken token = mTokenMap.get(_token);
7023            if (token != null) {
7024                mInputMonitor.resumeDispatchingLw(token);
7025            }
7026        }
7027    }
7028
7029    @Override
7030    public void setEventDispatching(boolean enabled) {
7031        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
7032                "setEventDispatching()")) {
7033            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
7034        }
7035
7036        synchronized (mWindowMap) {
7037            mEventDispatchingEnabled = enabled;
7038            if (mDisplayEnabled) {
7039                mInputMonitor.setEventDispatchingLw(enabled);
7040            }
7041        }
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);
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