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