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