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