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