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