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