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