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