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