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