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