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