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