WindowManagerService.java revision 0d674623facfbd3e9c520d2be4ed98977b92a1a2
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 keyguardGoingAway() {
5130        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5131                != PackageManager.PERMISSION_GRANTED) {
5132            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5133        }
5134        synchronized (mWindowMap) {
5135            mAnimator.mKeyguardGoingAway = true;
5136            requestTraversalLocked();
5137        }
5138    }
5139
5140    @Override
5141    public void closeSystemDialogs(String reason) {
5142        synchronized(mWindowMap) {
5143            final int numDisplays = mDisplayContents.size();
5144            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5145                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
5146                final int numWindows = windows.size();
5147                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
5148                    final WindowState w = windows.get(winNdx);
5149                    if (w.mHasSurface) {
5150                        try {
5151                            w.mClient.closeSystemDialogs(reason);
5152                        } catch (RemoteException e) {
5153                        }
5154                    }
5155                }
5156            }
5157        }
5158    }
5159
5160    static float fixScale(float scale) {
5161        if (scale < 0) scale = 0;
5162        else if (scale > 20) scale = 20;
5163        return Math.abs(scale);
5164    }
5165
5166    @Override
5167    public void setAnimationScale(int which, float scale) {
5168        if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
5169                "setAnimationScale()")) {
5170            throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
5171        }
5172
5173        scale = fixScale(scale);
5174        switch (which) {
5175            case 0: mWindowAnimationScale = scale; break;
5176            case 1: mTransitionAnimationScale = scale; break;
5177            case 2: mAnimatorDurationScale = scale; break;
5178        }
5179
5180        // Persist setting
5181        mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
5182    }
5183
5184    @Override
5185    public void setAnimationScales(float[] scales) {
5186        if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
5187                "setAnimationScale()")) {
5188            throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
5189        }
5190
5191        if (scales != null) {
5192            if (scales.length >= 1) {
5193                mWindowAnimationScale = fixScale(scales[0]);
5194            }
5195            if (scales.length >= 2) {
5196                mTransitionAnimationScale = fixScale(scales[1]);
5197            }
5198            if (scales.length >= 3) {
5199                setAnimatorDurationScale(fixScale(scales[2]));
5200            }
5201        }
5202
5203        // Persist setting
5204        mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
5205    }
5206
5207    private void setAnimatorDurationScale(float scale) {
5208        mAnimatorDurationScale = scale;
5209        ValueAnimator.setDurationScale(scale);
5210    }
5211
5212    @Override
5213    public float getAnimationScale(int which) {
5214        switch (which) {
5215            case 0: return mWindowAnimationScale;
5216            case 1: return mTransitionAnimationScale;
5217            case 2: return mAnimatorDurationScale;
5218        }
5219        return 0;
5220    }
5221
5222    @Override
5223    public float[] getAnimationScales() {
5224        return new float[] { mWindowAnimationScale, mTransitionAnimationScale,
5225                mAnimatorDurationScale };
5226    }
5227
5228    @Override
5229    public void registerPointerEventListener(PointerEventListener listener) {
5230        mPointerEventDispatcher.registerInputEventListener(listener);
5231    }
5232
5233    @Override
5234    public void unregisterPointerEventListener(PointerEventListener listener) {
5235        mPointerEventDispatcher.unregisterInputEventListener(listener);
5236    }
5237
5238    // Called by window manager policy. Not exposed externally.
5239    @Override
5240    public int getLidState() {
5241        int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY,
5242                InputManagerService.SW_LID);
5243        if (sw > 0) {
5244            // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL.
5245            return LID_CLOSED;
5246        } else if (sw == 0) {
5247            // Switch state: AKEY_STATE_UP.
5248            return LID_OPEN;
5249        } else {
5250            // Switch state: AKEY_STATE_UNKNOWN.
5251            return LID_ABSENT;
5252        }
5253    }
5254
5255    // Called by window manager policy.  Not exposed externally.
5256    @Override
5257    public void switchKeyboardLayout(int deviceId, int direction) {
5258        mInputManager.switchKeyboardLayout(deviceId, direction);
5259    }
5260
5261    // Called by window manager policy.  Not exposed externally.
5262    @Override
5263    public void shutdown(boolean confirm) {
5264        ShutdownThread.shutdown(mContext, confirm);
5265    }
5266
5267    // Called by window manager policy.  Not exposed externally.
5268    @Override
5269    public void rebootSafeMode(boolean confirm) {
5270        ShutdownThread.rebootSafeMode(mContext, confirm);
5271    }
5272
5273    public void setCurrentProfileIds(final int[] currentProfileIds) {
5274        synchronized (mWindowMap) {
5275            mCurrentProfileIds = currentProfileIds;
5276        }
5277    }
5278
5279    public void setCurrentUser(final int newUserId, final int[] currentProfileIds) {
5280        synchronized (mWindowMap) {
5281            mCurrentUserId = newUserId;
5282            mCurrentProfileIds = currentProfileIds;
5283            mAppTransition.setCurrentUser(newUserId);
5284            mPolicy.setCurrentUserLw(newUserId);
5285
5286            // Hide windows that should not be seen by the new user.
5287            final int numDisplays = mDisplayContents.size();
5288            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5289                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
5290                displayContent.switchUserStacks(newUserId);
5291                rebuildAppWindowListLocked(displayContent);
5292            }
5293            performLayoutAndPlaceSurfacesLocked();
5294        }
5295    }
5296
5297    /* Called by WindowState */
5298    boolean isCurrentProfileLocked(int userId) {
5299        if (userId == mCurrentUserId) return true;
5300        for (int i = 0; i < mCurrentProfileIds.length; i++) {
5301            if (mCurrentProfileIds[i] == userId) return true;
5302        }
5303        return false;
5304    }
5305
5306    public void enableScreenAfterBoot() {
5307        synchronized(mWindowMap) {
5308            if (DEBUG_BOOT) {
5309                RuntimeException here = new RuntimeException("here");
5310                here.fillInStackTrace();
5311                Slog.i(TAG, "enableScreenAfterBoot: mDisplayEnabled=" + mDisplayEnabled
5312                        + " mForceDisplayEnabled=" + mForceDisplayEnabled
5313                        + " mShowingBootMessages=" + mShowingBootMessages
5314                        + " mSystemBooted=" + mSystemBooted, here);
5315            }
5316            if (mSystemBooted) {
5317                return;
5318            }
5319            mSystemBooted = true;
5320            hideBootMessagesLocked();
5321            // If the screen still doesn't come up after 30 seconds, give
5322            // up and turn it on.
5323            mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30*1000);
5324        }
5325
5326        mPolicy.systemBooted();
5327
5328        performEnableScreen();
5329    }
5330
5331    @Override
5332    public void enableScreenIfNeeded() {
5333        synchronized (mWindowMap) {
5334            enableScreenIfNeededLocked();
5335        }
5336    }
5337
5338    void enableScreenIfNeededLocked() {
5339        if (DEBUG_BOOT) {
5340            RuntimeException here = new RuntimeException("here");
5341            here.fillInStackTrace();
5342            Slog.i(TAG, "enableScreenIfNeededLocked: mDisplayEnabled=" + mDisplayEnabled
5343                    + " mForceDisplayEnabled=" + mForceDisplayEnabled
5344                    + " mShowingBootMessages=" + mShowingBootMessages
5345                    + " mSystemBooted=" + mSystemBooted, here);
5346        }
5347        if (mDisplayEnabled) {
5348            return;
5349        }
5350        if (!mSystemBooted && !mShowingBootMessages) {
5351            return;
5352        }
5353        mH.sendEmptyMessage(H.ENABLE_SCREEN);
5354    }
5355
5356    public void performBootTimeout() {
5357        synchronized(mWindowMap) {
5358            if (mDisplayEnabled) {
5359                return;
5360            }
5361            Slog.w(TAG, "***** BOOT TIMEOUT: forcing display enabled");
5362            mForceDisplayEnabled = true;
5363        }
5364        performEnableScreen();
5365    }
5366
5367    public void performEnableScreen() {
5368        synchronized(mWindowMap) {
5369            if (DEBUG_BOOT) {
5370                RuntimeException here = new RuntimeException("here");
5371                here.fillInStackTrace();
5372                Slog.i(TAG, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled
5373                        + " mForceDisplayEnabled=" + mForceDisplayEnabled
5374                        + " mShowingBootMessages=" + mShowingBootMessages
5375                        + " mSystemBooted=" + mSystemBooted
5376                        + " mOnlyCore=" + mOnlyCore, here);
5377            }
5378            if (mDisplayEnabled) {
5379                return;
5380            }
5381            if (!mSystemBooted && !mShowingBootMessages) {
5382                return;
5383            }
5384
5385            if (!mForceDisplayEnabled) {
5386                // Don't enable the screen until all existing windows
5387                // have been drawn.
5388                boolean haveBootMsg = false;
5389                boolean haveApp = false;
5390                // if the wallpaper service is disabled on the device, we're never going to have
5391                // wallpaper, don't bother waiting for it
5392                boolean haveWallpaper = false;
5393                boolean wallpaperEnabled = mContext.getResources().getBoolean(
5394                        com.android.internal.R.bool.config_enableWallpaperService)
5395                        && !mOnlyCore;
5396                boolean haveKeyguard = true;
5397                // TODO(multidisplay): Expand to all displays?
5398                final WindowList windows = getDefaultWindowListLocked();
5399                final int N = windows.size();
5400                for (int i=0; i<N; i++) {
5401                    WindowState w = windows.get(i);
5402                    if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
5403                        return;
5404                    }
5405                    if (w.isDrawnLw()) {
5406                        if (w.mAttrs.type == TYPE_BOOT_PROGRESS) {
5407                            haveBootMsg = true;
5408                        } else if (w.mAttrs.type == TYPE_APPLICATION) {
5409                            haveApp = true;
5410                        } else if (w.mAttrs.type == TYPE_WALLPAPER) {
5411                            haveWallpaper = true;
5412                        } else if (w.mAttrs.type == TYPE_STATUS_BAR) {
5413                            haveKeyguard = mPolicy.isKeyguardDrawnLw();
5414                        }
5415                    }
5416                }
5417
5418                if (DEBUG_SCREEN_ON || DEBUG_BOOT) {
5419                    Slog.i(TAG, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages
5420                            + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp
5421                            + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled
5422                            + " haveKeyguard=" + haveKeyguard);
5423                }
5424
5425                // If we are turning on the screen to show the boot message,
5426                // don't do it until the boot message is actually displayed.
5427                if (!mSystemBooted && !haveBootMsg) {
5428                    return;
5429                }
5430
5431                // If we are turning on the screen after the boot is completed
5432                // normally, don't do so until we have the application and
5433                // wallpaper.
5434                if (mSystemBooted && ((!haveApp && !haveKeyguard) ||
5435                        (wallpaperEnabled && !haveWallpaper))) {
5436                    return;
5437                }
5438            }
5439
5440            mDisplayEnabled = true;
5441            if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG, "******************** ENABLING SCREEN!");
5442            if (false) {
5443                StringWriter sw = new StringWriter();
5444                PrintWriter pw = new FastPrintWriter(sw, false, 1024);
5445                this.dump(null, pw, null);
5446                pw.flush();
5447                Slog.i(TAG, sw.toString());
5448            }
5449            try {
5450                IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
5451                if (surfaceFlinger != null) {
5452                    //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
5453                    Parcel data = Parcel.obtain();
5454                    data.writeInterfaceToken("android.ui.ISurfaceComposer");
5455                    surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
5456                                            data, null, 0);
5457                    data.recycle();
5458                }
5459            } catch (RemoteException ex) {
5460                Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!");
5461            }
5462
5463            // Enable input dispatch.
5464            mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled);
5465        }
5466
5467        mPolicy.enableScreenAfterBoot();
5468
5469        // Make sure the last requested orientation has been applied.
5470        updateRotationUnchecked(false, false);
5471    }
5472
5473    public void showBootMessage(final CharSequence msg, final boolean always) {
5474        boolean first = false;
5475        synchronized(mWindowMap) {
5476            if (DEBUG_BOOT) {
5477                RuntimeException here = new RuntimeException("here");
5478                here.fillInStackTrace();
5479                Slog.i(TAG, "showBootMessage: msg=" + msg + " always=" + always
5480                        + " mAllowBootMessages=" + mAllowBootMessages
5481                        + " mShowingBootMessages=" + mShowingBootMessages
5482                        + " mSystemBooted=" + mSystemBooted, here);
5483            }
5484            if (!mAllowBootMessages) {
5485                return;
5486            }
5487            if (!mShowingBootMessages) {
5488                if (!always) {
5489                    return;
5490                }
5491                first = true;
5492            }
5493            if (mSystemBooted) {
5494                return;
5495            }
5496            mShowingBootMessages = true;
5497            mPolicy.showBootMessage(msg, always);
5498        }
5499        if (first) {
5500            performEnableScreen();
5501        }
5502    }
5503
5504    public void hideBootMessagesLocked() {
5505        if (DEBUG_BOOT) {
5506            RuntimeException here = new RuntimeException("here");
5507            here.fillInStackTrace();
5508            Slog.i(TAG, "hideBootMessagesLocked: mDisplayEnabled=" + mDisplayEnabled
5509                    + " mForceDisplayEnabled=" + mForceDisplayEnabled
5510                    + " mShowingBootMessages=" + mShowingBootMessages
5511                    + " mSystemBooted=" + mSystemBooted, here);
5512        }
5513        if (mShowingBootMessages) {
5514            mShowingBootMessages = false;
5515            mPolicy.hideBootMessages();
5516        }
5517    }
5518
5519    @Override
5520    public void setInTouchMode(boolean mode) {
5521        synchronized(mWindowMap) {
5522            mInTouchMode = mode;
5523        }
5524    }
5525
5526    public void showCircularDisplayMaskIfNeeded() {
5527        // we're fullscreen and not hosted in an ActivityView
5528        if (mContext.getResources().getBoolean(
5529                com.android.internal.R.bool.config_windowIsRound)) {
5530            mH.sendMessage(mH.obtainMessage(H.SHOW_DISPLAY_MASK));
5531        }
5532    }
5533
5534    public void showCircularMask() {
5535        synchronized(mWindowMap) {
5536
5537            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5538                    ">>> OPEN TRANSACTION showDisplayMask");
5539            SurfaceControl.openTransaction();
5540            try {
5541                // TODO(multi-display): support multiple displays
5542                if (mCircularDisplayMask == null) {
5543                    mCircularDisplayMask = new CircularDisplayMask(
5544                            getDefaultDisplayContentLocked().getDisplay(),
5545                            mFxSession,
5546                            mPolicy.windowTypeToLayerLw(
5547                                    WindowManager.LayoutParams.TYPE_POINTER)
5548                                    * TYPE_LAYER_MULTIPLIER + 10);
5549                }
5550                mCircularDisplayMask.setVisibility(true);
5551            } finally {
5552                SurfaceControl.closeTransaction();
5553                if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5554                        "<<< CLOSE TRANSACTION showDisplayMask");
5555            }
5556        }
5557    }
5558
5559    // TODO: more accounting of which pid(s) turned it on, keep count,
5560    // only allow disables from pids which have count on, etc.
5561    @Override
5562    public void showStrictModeViolation(boolean on) {
5563        int pid = Binder.getCallingPid();
5564        mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, pid));
5565    }
5566
5567    private void showStrictModeViolation(int arg, int pid) {
5568        final boolean on = arg != 0;
5569        synchronized(mWindowMap) {
5570            // Ignoring requests to enable the red border from clients
5571            // which aren't on screen.  (e.g. Broadcast Receivers in
5572            // the background..)
5573            if (on) {
5574                boolean isVisible = false;
5575                final int numDisplays = mDisplayContents.size();
5576                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5577                    final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
5578                    final int numWindows = windows.size();
5579                    for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
5580                        final WindowState ws = windows.get(winNdx);
5581                        if (ws.mSession.mPid == pid && ws.isVisibleLw()) {
5582                            isVisible = true;
5583                            break;
5584                        }
5585                    }
5586                }
5587                if (!isVisible) {
5588                    return;
5589                }
5590            }
5591
5592            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5593                    ">>> OPEN TRANSACTION showStrictModeViolation");
5594            SurfaceControl.openTransaction();
5595            try {
5596                // TODO(multi-display): support multiple displays
5597                if (mStrictModeFlash == null) {
5598                    mStrictModeFlash = new StrictModeFlash(
5599                            getDefaultDisplayContentLocked().getDisplay(), mFxSession);
5600                }
5601                mStrictModeFlash.setVisibility(on);
5602            } finally {
5603                SurfaceControl.closeTransaction();
5604                if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5605                        "<<< CLOSE TRANSACTION showStrictModeViolation");
5606            }
5607        }
5608    }
5609
5610    @Override
5611    public void setStrictModeVisualIndicatorPreference(String value) {
5612        SystemProperties.set(StrictMode.VISUAL_PROPERTY, value);
5613    }
5614
5615    /**
5616     * Takes a snapshot of the screen.  In landscape mode this grabs the whole screen.
5617     * In portrait mode, it grabs the upper region of the screen based on the vertical dimension
5618     * of the target image.
5619     *
5620     * @param displayId the Display to take a screenshot of.
5621     * @param width the width of the target bitmap
5622     * @param height the height of the target bitmap
5623     * @param force565 if true the returned bitmap will be RGB_565, otherwise it
5624     *                 will be the same config as the surface
5625     */
5626    @Override
5627    public Bitmap screenshotApplications(IBinder appToken, int displayId, int width,
5628            int height, boolean force565) {
5629        if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
5630                "screenshotApplications()")) {
5631            throw new SecurityException("Requires READ_FRAME_BUFFER permission");
5632        }
5633
5634        Bitmap rawss = null;
5635
5636        int maxLayer = 0;
5637        final Rect frame = new Rect();
5638
5639        float scale = 0;
5640        int dw, dh;
5641        int rot = Surface.ROTATION_0;
5642
5643        boolean screenshotReady;
5644        int minLayer;
5645        if (appToken == null) {
5646            screenshotReady = true;
5647            minLayer = 0;
5648        } else {
5649            screenshotReady = false;
5650            minLayer = Integer.MAX_VALUE;
5651        }
5652
5653        int retryCount = 0;
5654        WindowState appWin = null;
5655
5656        do {
5657            if (retryCount++ > 0) {
5658                try {
5659                    Thread.sleep(100);
5660                } catch (InterruptedException e) {
5661                }
5662            }
5663            synchronized(mWindowMap) {
5664                final DisplayContent displayContent = getDisplayContentLocked(displayId);
5665                if (displayContent == null) {
5666                    return null;
5667                }
5668                final DisplayInfo displayInfo = displayContent.getDisplayInfo();
5669                dw = displayInfo.logicalWidth;
5670                dh = displayInfo.logicalHeight;
5671
5672                int aboveAppLayer = mPolicy.windowTypeToLayerLw(TYPE_APPLICATION)
5673                        * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
5674                aboveAppLayer += TYPE_LAYER_MULTIPLIER;
5675
5676                boolean isImeTarget = mInputMethodTarget != null
5677                        && mInputMethodTarget.mAppToken != null
5678                        && mInputMethodTarget.mAppToken.appToken != null
5679                        && mInputMethodTarget.mAppToken.appToken.asBinder() == appToken;
5680
5681                // Figure out the part of the screen that is actually the app.
5682                boolean including = false;
5683                appWin = null;
5684                final WindowList windows = displayContent.getWindowList();
5685                final Rect stackBounds = new Rect();
5686                for (int i = windows.size() - 1; i >= 0; i--) {
5687                    WindowState ws = windows.get(i);
5688                    if (!ws.mHasSurface) {
5689                        continue;
5690                    }
5691                    if (ws.mLayer >= aboveAppLayer) {
5692                        continue;
5693                    }
5694                    // When we will skip windows: when we are not including
5695                    // ones behind a window we didn't skip, and we are actually
5696                    // taking a screenshot of a specific app.
5697                    if (!including && appToken != null) {
5698                        // Also, we can possibly skip this window if it is not
5699                        // an IME target or the application for the screenshot
5700                        // is not the current IME target.
5701                        if (!ws.mIsImWindow || !isImeTarget) {
5702                            // And finally, this window is of no interest if it
5703                            // is not associated with the screenshot app.
5704                            if (ws.mAppToken == null || ws.mAppToken.token != appToken) {
5705                                continue;
5706                            }
5707                            appWin = ws;
5708                            ws.getStackBounds(stackBounds);
5709                        }
5710                    }
5711
5712                    // We keep on including windows until we go past a full-screen
5713                    // window.
5714                    including = !ws.mIsImWindow && !ws.isFullscreen(dw, dh);
5715
5716                    final WindowStateAnimator winAnim = ws.mWinAnimator;
5717                    if (maxLayer < winAnim.mSurfaceLayer) {
5718                        maxLayer = winAnim.mSurfaceLayer;
5719                    }
5720                    if (minLayer > winAnim.mSurfaceLayer) {
5721                        minLayer = winAnim.mSurfaceLayer;
5722                    }
5723
5724                    // Don't include wallpaper in bounds calculation
5725                    if (!ws.mIsWallpaper) {
5726                        final Rect wf = ws.mFrame;
5727                        final Rect cr = ws.mContentInsets;
5728                        int left = wf.left + cr.left;
5729                        int top = wf.top + cr.top;
5730                        int right = wf.right - cr.right;
5731                        int bottom = wf.bottom - cr.bottom;
5732                        frame.union(left, top, right, bottom);
5733                        frame.intersect(stackBounds);
5734                    }
5735
5736                    if (ws.mAppToken != null && ws.mAppToken.token == appToken &&
5737                            ws.isDisplayedLw()) {
5738                        screenshotReady = true;
5739                    }
5740                }
5741
5742                if (appToken != null && appWin == null) {
5743                    // Can't find a window to snapshot.
5744                    if (DEBUG_SCREENSHOT) Slog.i(TAG,
5745                            "Screenshot: Couldn't find a surface matching " + appToken);
5746                    return null;
5747                }
5748                if (!screenshotReady) {
5749                    // Delay and hope that window gets drawn.
5750                    if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot: No image ready for " + appToken
5751                            + ", " + appWin + " drawState=" + appWin.mWinAnimator.mDrawState);
5752                    continue;
5753                }
5754
5755                // Constrain frame to the screen size.
5756                frame.intersect(0, 0, dw, dh);
5757
5758                if (frame.isEmpty() || maxLayer == 0) {
5759                    if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken
5760                            + ": returning null frame=" + frame.toShortString() + " maxLayer="
5761                            + maxLayer);
5762                    return null;
5763                }
5764
5765                // The screenshot API does not apply the current screen rotation.
5766                rot = getDefaultDisplayContentLocked().getDisplay().getRotation();
5767                int fw = frame.width();
5768                int fh = frame.height();
5769
5770                // Constrain thumbnail to smaller of screen width or height. Assumes aspect
5771                // of thumbnail is the same as the screen (in landscape) or square.
5772                scale = Math.max(width / (float) fw, height / (float) fh);
5773                /*
5774                float targetWidthScale = width / (float) fw;
5775                float targetHeightScale = height / (float) fh;
5776                if (fw <= fh) {
5777                    scale = targetWidthScale;
5778                    // If aspect of thumbnail is the same as the screen (in landscape),
5779                    // select the slightly larger value so we fill the entire bitmap
5780                    if (targetHeightScale > scale && (int) (targetHeightScale * fw) == width) {
5781                        scale = targetHeightScale;
5782                    }
5783                } else {
5784                    scale = targetHeightScale;
5785                    // If aspect of thumbnail is the same as the screen (in landscape),
5786                    // select the slightly larger value so we fill the entire bitmap
5787                    if (targetWidthScale > scale && (int) (targetWidthScale * fh) == height) {
5788                        scale = targetWidthScale;
5789                    }
5790                }
5791                */
5792
5793                // The screen shot will contain the entire screen.
5794                dw = (int)(dw*scale);
5795                dh = (int)(dh*scale);
5796                if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
5797                    int tmp = dw;
5798                    dw = dh;
5799                    dh = tmp;
5800                    rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90;
5801                }
5802                if (DEBUG_SCREENSHOT) {
5803                    Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to "
5804                            + maxLayer + " appToken=" + appToken);
5805                    for (int i = 0; i < windows.size(); i++) {
5806                        WindowState win = windows.get(i);
5807                        Slog.i(TAG, win + ": " + win.mLayer
5808                                + " animLayer=" + win.mWinAnimator.mAnimLayer
5809                                + " surfaceLayer=" + win.mWinAnimator.mSurfaceLayer);
5810                    }
5811                }
5812                // TODO: Replace 'false' in the following line with a variable that indicates
5813                // whether the screenshot should use the identity transformation matrix
5814                // (e.g., enable it when taking a screenshot for recents, since we might be in
5815                // the middle of the rotation animation, but don't want a rotated recent image).
5816                rawss = SurfaceControl.screenshot(dw, dh, minLayer, maxLayer, false);
5817            }
5818        } while (!screenshotReady && retryCount <= MAX_SCREENSHOT_RETRIES);
5819        if (retryCount > MAX_SCREENSHOT_RETRIES)  Slog.i(TAG, "Screenshot max retries " +
5820                retryCount + " of " + appToken + " appWin=" + (appWin == null ?
5821                        "null" : (appWin + " drawState=" + appWin.mWinAnimator.mDrawState)));
5822
5823        if (rawss == null) {
5824            Slog.w(TAG, "Screenshot failure taking screenshot for (" + dw + "x" + dh
5825                    + ") to layer " + maxLayer);
5826            return null;
5827        }
5828
5829        Bitmap bm = Bitmap.createBitmap(width, height, force565 ? Config.RGB_565 : rawss.getConfig());
5830        bm.eraseColor(0xFF000000);
5831        frame.scale(scale);
5832        Matrix matrix = new Matrix();
5833        ScreenRotationAnimation.createRotationMatrix(rot, dw, dh, matrix);
5834        // TODO: Test for RTL vs. LTR and use frame.right-width instead of -frame.left
5835        matrix.postTranslate(-FloatMath.ceil(frame.left), -FloatMath.ceil(frame.top));
5836        Canvas canvas = new Canvas(bm);
5837        canvas.drawBitmap(rawss, matrix, null);
5838        canvas.setBitmap(null);
5839
5840        if (DEBUG_SCREENSHOT) {
5841            // TEST IF IT's ALL BLACK
5842            int[] buffer = new int[bm.getWidth() * bm.getHeight()];
5843            bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight());
5844            boolean allBlack = true;
5845            final int firstColor = buffer[0];
5846            for (int i = 0; i < buffer.length; i++) {
5847                if (buffer[i] != firstColor) {
5848                    allBlack = false;
5849                    break;
5850                }
5851            }
5852            if (allBlack) {
5853                Slog.i(TAG, "Screenshot " + appWin + " was monochrome(" +
5854                        Integer.toHexString(firstColor) + ")! mSurfaceLayer=" +
5855                        (appWin != null ? appWin.mWinAnimator.mSurfaceLayer : "null") +
5856                        " minLayer=" + minLayer + " maxLayer=" + maxLayer);
5857            }
5858        }
5859
5860        rawss.recycle();
5861        return bm;
5862    }
5863
5864    /**
5865     * Freeze rotation changes.  (Enable "rotation lock".)
5866     * Persists across reboots.
5867     * @param rotation The desired rotation to freeze to, or -1 to use the
5868     * current rotation.
5869     */
5870    @Override
5871    public void freezeRotation(int rotation) {
5872        if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
5873                "freezeRotation()")) {
5874            throw new SecurityException("Requires SET_ORIENTATION permission");
5875        }
5876        if (rotation < -1 || rotation > Surface.ROTATION_270) {
5877            throw new IllegalArgumentException("Rotation argument must be -1 or a valid "
5878                    + "rotation constant.");
5879        }
5880
5881        if (DEBUG_ORIENTATION) Slog.v(TAG, "freezeRotation: mRotation=" + mRotation);
5882
5883        long origId = Binder.clearCallingIdentity();
5884        try {
5885            mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED,
5886                    rotation == -1 ? mRotation : rotation);
5887        } finally {
5888            Binder.restoreCallingIdentity(origId);
5889        }
5890
5891        updateRotationUnchecked(false, false);
5892    }
5893
5894    /**
5895     * Thaw rotation changes.  (Disable "rotation lock".)
5896     * Persists across reboots.
5897     */
5898    @Override
5899    public void thawRotation() {
5900        if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
5901                "thawRotation()")) {
5902            throw new SecurityException("Requires SET_ORIENTATION permission");
5903        }
5904
5905        if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation);
5906
5907        long origId = Binder.clearCallingIdentity();
5908        try {
5909            mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE,
5910                    777); // rot not used
5911        } finally {
5912            Binder.restoreCallingIdentity(origId);
5913        }
5914
5915        updateRotationUnchecked(false, false);
5916    }
5917
5918    /**
5919     * Recalculate the current rotation.
5920     *
5921     * Called by the window manager policy whenever the state of the system changes
5922     * such that the current rotation might need to be updated, such as when the
5923     * device is docked or rotated into a new posture.
5924     */
5925    @Override
5926    public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
5927        updateRotationUnchecked(alwaysSendConfiguration, forceRelayout);
5928    }
5929
5930    /**
5931     * Temporarily pauses rotation changes until resumed.
5932     *
5933     * This can be used to prevent rotation changes from occurring while the user is
5934     * performing certain operations, such as drag and drop.
5935     *
5936     * This call nests and must be matched by an equal number of calls to
5937     * {@link #resumeRotationLocked}.
5938     */
5939    void pauseRotationLocked() {
5940        mDeferredRotationPauseCount += 1;
5941    }
5942
5943    /**
5944     * Resumes normal rotation changes after being paused.
5945     */
5946    void resumeRotationLocked() {
5947        if (mDeferredRotationPauseCount > 0) {
5948            mDeferredRotationPauseCount -= 1;
5949            if (mDeferredRotationPauseCount == 0) {
5950                boolean changed = updateRotationUncheckedLocked(false);
5951                if (changed) {
5952                    mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
5953                }
5954            }
5955        }
5956    }
5957
5958    public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) {
5959        if(DEBUG_ORIENTATION) Slog.v(TAG, "updateRotationUnchecked("
5960                   + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")");
5961
5962        long origId = Binder.clearCallingIdentity();
5963        boolean changed;
5964        synchronized(mWindowMap) {
5965            changed = updateRotationUncheckedLocked(false);
5966            if (!changed || forceRelayout) {
5967                getDefaultDisplayContentLocked().layoutNeeded = true;
5968                performLayoutAndPlaceSurfacesLocked();
5969            }
5970        }
5971
5972        if (changed || alwaysSendConfiguration) {
5973            sendNewConfiguration();
5974        }
5975
5976        Binder.restoreCallingIdentity(origId);
5977    }
5978
5979    // TODO(multidisplay): Rotate any display?
5980    /**
5981     * Updates the current rotation.
5982     *
5983     * Returns true if the rotation has been changed.  In this case YOU
5984     * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN.
5985     */
5986    public boolean updateRotationUncheckedLocked(boolean inTransaction) {
5987        if (mDeferredRotationPauseCount > 0) {
5988            // Rotation updates have been paused temporarily.  Defer the update until
5989            // updates have been resumed.
5990            if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, rotation is paused.");
5991            return false;
5992        }
5993
5994        ScreenRotationAnimation screenRotationAnimation =
5995                mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
5996        if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
5997            // Rotation updates cannot be performed while the previous rotation change
5998            // animation is still in progress.  Skip this update.  We will try updating
5999            // again after the animation is finished and the display is unfrozen.
6000            if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, animation in progress.");
6001            return false;
6002        }
6003
6004        if (!mDisplayEnabled) {
6005            // No point choosing a rotation if the display is not enabled.
6006            if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, display is not enabled.");
6007            return false;
6008        }
6009
6010        // TODO: Implement forced rotation changes.
6011        //       Set mAltOrientation to indicate that the application is receiving
6012        //       an orientation that has different metrics than it expected.
6013        //       eg. Portrait instead of Landscape.
6014
6015        int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation);
6016        boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw(
6017                mForcedAppOrientation, rotation);
6018
6019        if (DEBUG_ORIENTATION) {
6020            Slog.v(TAG, "Application requested orientation "
6021                    + mForcedAppOrientation + ", got rotation " + rotation
6022                    + " which has " + (altOrientation ? "incompatible" : "compatible")
6023                    + " metrics");
6024        }
6025
6026        if (mRotation == rotation && mAltOrientation == altOrientation) {
6027            // No change.
6028            return false;
6029        }
6030
6031        if (DEBUG_ORIENTATION) {
6032            Slog.v(TAG,
6033                "Rotation changed to " + rotation + (altOrientation ? " (alt)" : "")
6034                + " from " + mRotation + (mAltOrientation ? " (alt)" : "")
6035                + ", forceApp=" + mForcedAppOrientation);
6036        }
6037
6038        mRotation = rotation;
6039        mAltOrientation = altOrientation;
6040        mPolicy.setRotationLw(mRotation);
6041
6042        mWindowsFreezingScreen = true;
6043        mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
6044        mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION);
6045        mWaitingForConfig = true;
6046        final DisplayContent displayContent = getDefaultDisplayContentLocked();
6047        displayContent.layoutNeeded = true;
6048        final int[] anim = new int[2];
6049        if (displayContent.isDimming()) {
6050            anim[0] = anim[1] = 0;
6051        } else {
6052            mPolicy.selectRotationAnimationLw(anim);
6053        }
6054        startFreezingDisplayLocked(inTransaction, anim[0], anim[1]);
6055        // startFreezingDisplayLocked can reset the ScreenRotationAnimation.
6056        screenRotationAnimation =
6057                mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
6058
6059        // We need to update our screen size information to match the new
6060        // rotation.  Note that this is redundant with the later call to
6061        // sendNewConfiguration() that must be called after this function
6062        // returns...  however we need to do the screen size part of that
6063        // before then so we have the correct size to use when initializing
6064        // the rotation animation for the new rotation.
6065        computeScreenConfigurationLocked(null);
6066
6067        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
6068        if (!inTransaction) {
6069            if (SHOW_TRANSACTIONS) {
6070                Slog.i(TAG, ">>> OPEN TRANSACTION setRotationUnchecked");
6071            }
6072            SurfaceControl.openTransaction();
6073        }
6074        try {
6075            // NOTE: We disable the rotation in the emulator because
6076            //       it doesn't support hardware OpenGL emulation yet.
6077            if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
6078                    && screenRotationAnimation.hasScreenshot()) {
6079                if (screenRotationAnimation.setRotationInTransaction(
6080                        rotation, mFxSession,
6081                        MAX_ANIMATION_DURATION, mTransitionAnimationScale,
6082                        displayInfo.logicalWidth, displayInfo.logicalHeight)) {
6083                    scheduleAnimationLocked();
6084                }
6085            }
6086
6087            mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
6088        } finally {
6089            if (!inTransaction) {
6090                SurfaceControl.closeTransaction();
6091                if (SHOW_LIGHT_TRANSACTIONS) {
6092                    Slog.i(TAG, "<<< CLOSE TRANSACTION setRotationUnchecked");
6093                }
6094            }
6095        }
6096
6097        final WindowList windows = displayContent.getWindowList();
6098        for (int i = windows.size() - 1; i >= 0; i--) {
6099            WindowState w = windows.get(i);
6100            if (w.mHasSurface) {
6101                if (DEBUG_ORIENTATION) Slog.v(TAG, "Set mOrientationChanging of " + w);
6102                w.mOrientationChanging = true;
6103                mInnerFields.mOrientationChangeComplete = false;
6104            }
6105            w.mLastFreezeDuration = 0;
6106        }
6107
6108        for (int i=mRotationWatchers.size()-1; i>=0; i--) {
6109            try {
6110                mRotationWatchers.get(i).watcher.onRotationChanged(rotation);
6111            } catch (RemoteException e) {
6112            }
6113        }
6114
6115        //TODO (multidisplay): Magnification is supported only for the default display.
6116        if (mAccessibilityController != null
6117                && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) {
6118            mAccessibilityController.onRotationChangedLocked(getDefaultDisplayContentLocked(), rotation);
6119        }
6120
6121        return true;
6122    }
6123
6124    @Override
6125    public int getRotation() {
6126        return mRotation;
6127    }
6128
6129    @Override
6130    public boolean isRotationFrozen() {
6131        return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED;
6132    }
6133
6134    @Override
6135    public int watchRotation(IRotationWatcher watcher) {
6136        final IBinder watcherBinder = watcher.asBinder();
6137        IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
6138            @Override
6139            public void binderDied() {
6140                synchronized (mWindowMap) {
6141                    for (int i=0; i<mRotationWatchers.size(); i++) {
6142                        if (watcherBinder == mRotationWatchers.get(i).watcher.asBinder()) {
6143                            RotationWatcher removed = mRotationWatchers.remove(i);
6144                            IBinder binder = removed.watcher.asBinder();
6145                            if (binder != null) {
6146                                binder.unlinkToDeath(this, 0);
6147                            }
6148                            i--;
6149                        }
6150                    }
6151                }
6152            }
6153        };
6154
6155        synchronized (mWindowMap) {
6156            try {
6157                watcher.asBinder().linkToDeath(dr, 0);
6158                mRotationWatchers.add(new RotationWatcher(watcher, dr));
6159            } catch (RemoteException e) {
6160                // Client died, no cleanup needed.
6161            }
6162
6163            return mRotation;
6164        }
6165    }
6166
6167    @Override
6168    public void removeRotationWatcher(IRotationWatcher watcher) {
6169        final IBinder watcherBinder = watcher.asBinder();
6170        synchronized (mWindowMap) {
6171            for (int i=0; i<mRotationWatchers.size(); i++) {
6172                RotationWatcher rotationWatcher = mRotationWatchers.get(i);
6173                if (watcherBinder == rotationWatcher.watcher.asBinder()) {
6174                    RotationWatcher removed = mRotationWatchers.remove(i);
6175                    IBinder binder = removed.watcher.asBinder();
6176                    if (binder != null) {
6177                        binder.unlinkToDeath(removed.deathRecipient, 0);
6178                    }
6179                    i--;
6180                }
6181            }
6182        }
6183    }
6184
6185    /**
6186     * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact
6187     * theme attribute) on devices that feature a physical options menu key attempt to position
6188     * their menu panel window along the edge of the screen nearest the physical menu key.
6189     * This lowers the travel distance between invoking the menu panel and selecting
6190     * a menu option.
6191     *
6192     * This method helps control where that menu is placed. Its current implementation makes
6193     * assumptions about the menu key and its relationship to the screen based on whether
6194     * the device's natural orientation is portrait (width < height) or landscape.
6195     *
6196     * The menu key is assumed to be located along the bottom edge of natural-portrait
6197     * devices and along the right edge of natural-landscape devices. If these assumptions
6198     * do not hold for the target device, this method should be changed to reflect that.
6199     *
6200     * @return A {@link Gravity} value for placing the options menu window
6201     */
6202    @Override
6203    public int getPreferredOptionsPanelGravity() {
6204        synchronized (mWindowMap) {
6205            final int rotation = getRotation();
6206
6207            // TODO(multidisplay): Assume that such devices physical keys are on the main screen.
6208            final DisplayContent displayContent = getDefaultDisplayContentLocked();
6209            if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) {
6210                // On devices with a natural orientation of portrait
6211                switch (rotation) {
6212                    default:
6213                    case Surface.ROTATION_0:
6214                        return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6215                    case Surface.ROTATION_90:
6216                        return Gravity.RIGHT | Gravity.BOTTOM;
6217                    case Surface.ROTATION_180:
6218                        return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6219                    case Surface.ROTATION_270:
6220                        return Gravity.START | Gravity.BOTTOM;
6221                }
6222            }
6223
6224            // On devices with a natural orientation of landscape
6225            switch (rotation) {
6226                default:
6227                case Surface.ROTATION_0:
6228                    return Gravity.RIGHT | Gravity.BOTTOM;
6229                case Surface.ROTATION_90:
6230                    return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6231                case Surface.ROTATION_180:
6232                    return Gravity.START | Gravity.BOTTOM;
6233                case Surface.ROTATION_270:
6234                    return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6235            }
6236        }
6237    }
6238
6239    /**
6240     * Starts the view server on the specified port.
6241     *
6242     * @param port The port to listener to.
6243     *
6244     * @return True if the server was successfully started, false otherwise.
6245     *
6246     * @see com.android.server.wm.ViewServer
6247     * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT
6248     */
6249    @Override
6250    public boolean startViewServer(int port) {
6251        if (isSystemSecure()) {
6252            return false;
6253        }
6254
6255        if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) {
6256            return false;
6257        }
6258
6259        if (port < 1024) {
6260            return false;
6261        }
6262
6263        if (mViewServer != null) {
6264            if (!mViewServer.isRunning()) {
6265                try {
6266                    return mViewServer.start();
6267                } catch (IOException e) {
6268                    Slog.w(TAG, "View server did not start");
6269                }
6270            }
6271            return false;
6272        }
6273
6274        try {
6275            mViewServer = new ViewServer(this, port);
6276            return mViewServer.start();
6277        } catch (IOException e) {
6278            Slog.w(TAG, "View server did not start");
6279        }
6280        return false;
6281    }
6282
6283    private boolean isSystemSecure() {
6284        return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) &&
6285                "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
6286    }
6287
6288    /**
6289     * Stops the view server if it exists.
6290     *
6291     * @return True if the server stopped, false if it wasn't started or
6292     *         couldn't be stopped.
6293     *
6294     * @see com.android.server.wm.ViewServer
6295     */
6296    @Override
6297    public boolean stopViewServer() {
6298        if (isSystemSecure()) {
6299            return false;
6300        }
6301
6302        if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) {
6303            return false;
6304        }
6305
6306        if (mViewServer != null) {
6307            return mViewServer.stop();
6308        }
6309        return false;
6310    }
6311
6312    /**
6313     * Indicates whether the view server is running.
6314     *
6315     * @return True if the server is running, false otherwise.
6316     *
6317     * @see com.android.server.wm.ViewServer
6318     */
6319    @Override
6320    public boolean isViewServerRunning() {
6321        if (isSystemSecure()) {
6322            return false;
6323        }
6324
6325        if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) {
6326            return false;
6327        }
6328
6329        return mViewServer != null && mViewServer.isRunning();
6330    }
6331
6332    /**
6333     * Lists all availble windows in the system. The listing is written in the
6334     * specified Socket's output stream with the following syntax:
6335     * windowHashCodeInHexadecimal windowName
6336     * Each line of the ouput represents a different window.
6337     *
6338     * @param client The remote client to send the listing to.
6339     * @return False if an error occured, true otherwise.
6340     */
6341    boolean viewServerListWindows(Socket client) {
6342        if (isSystemSecure()) {
6343            return false;
6344        }
6345
6346        boolean result = true;
6347
6348        WindowList windows = new WindowList();
6349        synchronized (mWindowMap) {
6350            //noinspection unchecked
6351            final int numDisplays = mDisplayContents.size();
6352            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
6353                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
6354                windows.addAll(displayContent.getWindowList());
6355            }
6356        }
6357
6358        BufferedWriter out = null;
6359
6360        // Any uncaught exception will crash the system process
6361        try {
6362            OutputStream clientStream = client.getOutputStream();
6363            out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
6364
6365            final int count = windows.size();
6366            for (int i = 0; i < count; i++) {
6367                final WindowState w = windows.get(i);
6368                out.write(Integer.toHexString(System.identityHashCode(w)));
6369                out.write(' ');
6370                out.append(w.mAttrs.getTitle());
6371                out.write('\n');
6372            }
6373
6374            out.write("DONE.\n");
6375            out.flush();
6376        } catch (Exception e) {
6377            result = false;
6378        } finally {
6379            if (out != null) {
6380                try {
6381                    out.close();
6382                } catch (IOException e) {
6383                    result = false;
6384                }
6385            }
6386        }
6387
6388        return result;
6389    }
6390
6391    // TODO(multidisplay): Extend to multiple displays.
6392    /**
6393     * Returns the focused window in the following format:
6394     * windowHashCodeInHexadecimal windowName
6395     *
6396     * @param client The remote client to send the listing to.
6397     * @return False if an error occurred, true otherwise.
6398     */
6399    boolean viewServerGetFocusedWindow(Socket client) {
6400        if (isSystemSecure()) {
6401            return false;
6402        }
6403
6404        boolean result = true;
6405
6406        WindowState focusedWindow = getFocusedWindow();
6407
6408        BufferedWriter out = null;
6409
6410        // Any uncaught exception will crash the system process
6411        try {
6412            OutputStream clientStream = client.getOutputStream();
6413            out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
6414
6415            if(focusedWindow != null) {
6416                out.write(Integer.toHexString(System.identityHashCode(focusedWindow)));
6417                out.write(' ');
6418                out.append(focusedWindow.mAttrs.getTitle());
6419            }
6420            out.write('\n');
6421            out.flush();
6422        } catch (Exception e) {
6423            result = false;
6424        } finally {
6425            if (out != null) {
6426                try {
6427                    out.close();
6428                } catch (IOException e) {
6429                    result = false;
6430                }
6431            }
6432        }
6433
6434        return result;
6435    }
6436
6437    /**
6438     * Sends a command to a target window. The result of the command, if any, will be
6439     * written in the output stream of the specified socket.
6440     *
6441     * The parameters must follow this syntax:
6442     * windowHashcode extra
6443     *
6444     * Where XX is the length in characeters of the windowTitle.
6445     *
6446     * The first parameter is the target window. The window with the specified hashcode
6447     * will be the target. If no target can be found, nothing happens. The extra parameters
6448     * will be delivered to the target window and as parameters to the command itself.
6449     *
6450     * @param client The remote client to sent the result, if any, to.
6451     * @param command The command to execute.
6452     * @param parameters The command parameters.
6453     *
6454     * @return True if the command was successfully delivered, false otherwise. This does
6455     *         not indicate whether the command itself was successful.
6456     */
6457    boolean viewServerWindowCommand(Socket client, String command, String parameters) {
6458        if (isSystemSecure()) {
6459            return false;
6460        }
6461
6462        boolean success = true;
6463        Parcel data = null;
6464        Parcel reply = null;
6465
6466        BufferedWriter out = null;
6467
6468        // Any uncaught exception will crash the system process
6469        try {
6470            // Find the hashcode of the window
6471            int index = parameters.indexOf(' ');
6472            if (index == -1) {
6473                index = parameters.length();
6474            }
6475            final String code = parameters.substring(0, index);
6476            int hashCode = (int) Long.parseLong(code, 16);
6477
6478            // Extract the command's parameter after the window description
6479            if (index < parameters.length()) {
6480                parameters = parameters.substring(index + 1);
6481            } else {
6482                parameters = "";
6483            }
6484
6485            final WindowState window = findWindow(hashCode);
6486            if (window == null) {
6487                return false;
6488            }
6489
6490            data = Parcel.obtain();
6491            data.writeInterfaceToken("android.view.IWindow");
6492            data.writeString(command);
6493            data.writeString(parameters);
6494            data.writeInt(1);
6495            ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0);
6496
6497            reply = Parcel.obtain();
6498
6499            final IBinder binder = window.mClient.asBinder();
6500            // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER
6501            binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
6502
6503            reply.readException();
6504
6505            if (!client.isOutputShutdown()) {
6506                out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
6507                out.write("DONE\n");
6508                out.flush();
6509            }
6510
6511        } catch (Exception e) {
6512            Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e);
6513            success = false;
6514        } finally {
6515            if (data != null) {
6516                data.recycle();
6517            }
6518            if (reply != null) {
6519                reply.recycle();
6520            }
6521            if (out != null) {
6522                try {
6523                    out.close();
6524                } catch (IOException e) {
6525
6526                }
6527            }
6528        }
6529
6530        return success;
6531    }
6532
6533    public void addWindowChangeListener(WindowChangeListener listener) {
6534        synchronized(mWindowMap) {
6535            mWindowChangeListeners.add(listener);
6536        }
6537    }
6538
6539    public void removeWindowChangeListener(WindowChangeListener listener) {
6540        synchronized(mWindowMap) {
6541            mWindowChangeListeners.remove(listener);
6542        }
6543    }
6544
6545    private void notifyWindowsChanged() {
6546        WindowChangeListener[] windowChangeListeners;
6547        synchronized(mWindowMap) {
6548            if(mWindowChangeListeners.isEmpty()) {
6549                return;
6550            }
6551            windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
6552            windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
6553        }
6554        int N = windowChangeListeners.length;
6555        for(int i = 0; i < N; i++) {
6556            windowChangeListeners[i].windowsChanged();
6557        }
6558    }
6559
6560    private void notifyFocusChanged() {
6561        WindowChangeListener[] windowChangeListeners;
6562        synchronized(mWindowMap) {
6563            if(mWindowChangeListeners.isEmpty()) {
6564                return;
6565            }
6566            windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
6567            windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
6568        }
6569        int N = windowChangeListeners.length;
6570        for(int i = 0; i < N; i++) {
6571            windowChangeListeners[i].focusChanged();
6572        }
6573    }
6574
6575    private WindowState findWindow(int hashCode) {
6576        if (hashCode == -1) {
6577            // TODO(multidisplay): Extend to multiple displays.
6578            return getFocusedWindow();
6579        }
6580
6581        synchronized (mWindowMap) {
6582            final int numDisplays = mDisplayContents.size();
6583            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
6584                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
6585                final int numWindows = windows.size();
6586                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
6587                    final WindowState w = windows.get(winNdx);
6588                    if (System.identityHashCode(w) == hashCode) {
6589                        return w;
6590                    }
6591                }
6592            }
6593        }
6594
6595        return null;
6596    }
6597
6598    /*
6599     * Instruct the Activity Manager to fetch the current configuration and broadcast
6600     * that to config-changed listeners if appropriate.
6601     */
6602    void sendNewConfiguration() {
6603        try {
6604            mActivityManager.updateConfiguration(null);
6605        } catch (RemoteException e) {
6606        }
6607    }
6608
6609    public Configuration computeNewConfiguration() {
6610        synchronized (mWindowMap) {
6611            Configuration config = computeNewConfigurationLocked();
6612            if (config == null && mWaitingForConfig) {
6613                // Nothing changed but we are waiting for something... stop that!
6614                mWaitingForConfig = false;
6615                mLastFinishedFreezeSource = "new-config";
6616                performLayoutAndPlaceSurfacesLocked();
6617            }
6618            return config;
6619        }
6620    }
6621
6622    Configuration computeNewConfigurationLocked() {
6623        Configuration config = new Configuration();
6624        config.fontScale = 0;
6625        if (!computeScreenConfigurationLocked(config)) {
6626            return null;
6627        }
6628        return config;
6629    }
6630
6631    private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int dw, int dh) {
6632        // TODO: Multidisplay: for now only use with default display.
6633        final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation);
6634        if (width < displayInfo.smallestNominalAppWidth) {
6635            displayInfo.smallestNominalAppWidth = width;
6636        }
6637        if (width > displayInfo.largestNominalAppWidth) {
6638            displayInfo.largestNominalAppWidth = width;
6639        }
6640        final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation);
6641        if (height < displayInfo.smallestNominalAppHeight) {
6642            displayInfo.smallestNominalAppHeight = height;
6643        }
6644        if (height > displayInfo.largestNominalAppHeight) {
6645            displayInfo.largestNominalAppHeight = height;
6646        }
6647    }
6648
6649    private int reduceConfigLayout(int curLayout, int rotation, float density,
6650            int dw, int dh) {
6651        // TODO: Multidisplay: for now only use with default display.
6652        // Get the app screen size at this rotation.
6653        int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation);
6654        int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation);
6655
6656        // Compute the screen layout size class for this rotation.
6657        int longSize = w;
6658        int shortSize = h;
6659        if (longSize < shortSize) {
6660            int tmp = longSize;
6661            longSize = shortSize;
6662            shortSize = tmp;
6663        }
6664        longSize = (int)(longSize/density);
6665        shortSize = (int)(shortSize/density);
6666        return Configuration.reduceScreenLayout(curLayout, longSize, shortSize);
6667    }
6668
6669    private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated,
6670                  int dw, int dh, float density, Configuration outConfig) {
6671        // TODO: Multidisplay: for now only use with default display.
6672
6673        // We need to determine the smallest width that will occur under normal
6674        // operation.  To this, start with the base screen size and compute the
6675        // width under the different possible rotations.  We need to un-rotate
6676        // the current screen dimensions before doing this.
6677        int unrotDw, unrotDh;
6678        if (rotated) {
6679            unrotDw = dh;
6680            unrotDh = dw;
6681        } else {
6682            unrotDw = dw;
6683            unrotDh = dh;
6684        }
6685        displayInfo.smallestNominalAppWidth = 1<<30;
6686        displayInfo.smallestNominalAppHeight = 1<<30;
6687        displayInfo.largestNominalAppWidth = 0;
6688        displayInfo.largestNominalAppHeight = 0;
6689        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, unrotDw, unrotDh);
6690        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, unrotDh, unrotDw);
6691        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, unrotDw, unrotDh);
6692        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, unrotDh, unrotDw);
6693        int sl = Configuration.resetScreenLayout(outConfig.screenLayout);
6694        sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh);
6695        sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw);
6696        sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh);
6697        sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw);
6698        outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density);
6699        outConfig.screenLayout = sl;
6700    }
6701
6702    private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm,
6703            int dw, int dh) {
6704        // TODO: Multidisplay: for now only use with default display.
6705        dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation);
6706        dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation);
6707        float scale = CompatibilityInfo.computeCompatibleScaling(dm, null);
6708        int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f);
6709        if (curSize == 0 || size < curSize) {
6710            curSize = size;
6711        }
6712        return curSize;
6713    }
6714
6715    private int computeCompatSmallestWidth(boolean rotated, DisplayMetrics dm, int dw, int dh) {
6716        // TODO: Multidisplay: for now only use with default display.
6717        mTmpDisplayMetrics.setTo(dm);
6718        final DisplayMetrics tmpDm = mTmpDisplayMetrics;
6719        final int unrotDw, unrotDh;
6720        if (rotated) {
6721            unrotDw = dh;
6722            unrotDh = dw;
6723        } else {
6724            unrotDw = dw;
6725            unrotDh = dh;
6726        }
6727        int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, tmpDm, unrotDw, unrotDh);
6728        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, tmpDm, unrotDh, unrotDw);
6729        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, tmpDm, unrotDw, unrotDh);
6730        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, tmpDm, unrotDh, unrotDw);
6731        return sw;
6732    }
6733
6734    boolean computeScreenConfigurationLocked(Configuration config) {
6735        if (!mDisplayReady) {
6736            return false;
6737        }
6738
6739        // TODO(multidisplay): For now, apply Configuration to main screen only.
6740        final DisplayContent displayContent = getDefaultDisplayContentLocked();
6741
6742        // Use the effective "visual" dimensions based on current rotation
6743        final boolean rotated = (mRotation == Surface.ROTATION_90
6744                || mRotation == Surface.ROTATION_270);
6745        final int realdw = rotated ?
6746                displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth;
6747        final int realdh = rotated ?
6748                displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight;
6749        int dw = realdw;
6750        int dh = realdh;
6751
6752        if (mAltOrientation) {
6753            if (realdw > realdh) {
6754                // Turn landscape into portrait.
6755                int maxw = (int)(realdh/1.3f);
6756                if (maxw < realdw) {
6757                    dw = maxw;
6758                }
6759            } else {
6760                // Turn portrait into landscape.
6761                int maxh = (int)(realdw/1.3f);
6762                if (maxh < realdh) {
6763                    dh = maxh;
6764                }
6765            }
6766        }
6767
6768        if (config != null) {
6769            config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT :
6770                    Configuration.ORIENTATION_LANDSCAPE;
6771        }
6772
6773        // Update application display metrics.
6774        final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation);
6775        final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation);
6776        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
6777        synchronized(displayContent.mDisplaySizeLock) {
6778            displayInfo.rotation = mRotation;
6779            displayInfo.logicalWidth = dw;
6780            displayInfo.logicalHeight = dh;
6781            displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity;
6782            displayInfo.appWidth = appWidth;
6783            displayInfo.appHeight = appHeight;
6784            displayInfo.getLogicalMetrics(mRealDisplayMetrics,
6785                    CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
6786            displayInfo.getAppMetrics(mDisplayMetrics);
6787            mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
6788                    displayContent.getDisplayId(), displayInfo);
6789        }
6790        if (false) {
6791            Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight);
6792        }
6793
6794        final DisplayMetrics dm = mDisplayMetrics;
6795        mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm,
6796                mCompatDisplayMetrics);
6797
6798        if (config != null) {
6799            config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation)
6800                    / dm.density);
6801            config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation)
6802                    / dm.density);
6803            computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, dm.density, config);
6804
6805            config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale);
6806            config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale);
6807            config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh);
6808            config.densityDpi = displayContent.mBaseDisplayDensity;
6809
6810            // Update the configuration based on available input devices, lid switch,
6811            // and platform configuration.
6812            config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
6813            config.keyboard = Configuration.KEYBOARD_NOKEYS;
6814            config.navigation = Configuration.NAVIGATION_NONAV;
6815
6816            int keyboardPresence = 0;
6817            int navigationPresence = 0;
6818            final InputDevice[] devices = mInputManager.getInputDevices();
6819            final int len = devices.length;
6820            for (int i = 0; i < len; i++) {
6821                InputDevice device = devices[i];
6822                if (!device.isVirtual()) {
6823                    final int sources = device.getSources();
6824                    final int presenceFlag = device.isExternal() ?
6825                            WindowManagerPolicy.PRESENCE_EXTERNAL :
6826                                    WindowManagerPolicy.PRESENCE_INTERNAL;
6827
6828                    if (mIsTouchDevice) {
6829                        if ((sources & InputDevice.SOURCE_TOUCHSCREEN) ==
6830                                InputDevice.SOURCE_TOUCHSCREEN) {
6831                            config.touchscreen = Configuration.TOUCHSCREEN_FINGER;
6832                        }
6833                    } else {
6834                        config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
6835                    }
6836
6837                    if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) {
6838                        config.navigation = Configuration.NAVIGATION_TRACKBALL;
6839                        navigationPresence |= presenceFlag;
6840                    } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD
6841                            && config.navigation == Configuration.NAVIGATION_NONAV) {
6842                        config.navigation = Configuration.NAVIGATION_DPAD;
6843                        navigationPresence |= presenceFlag;
6844                    }
6845
6846                    if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {
6847                        config.keyboard = Configuration.KEYBOARD_QWERTY;
6848                        keyboardPresence |= presenceFlag;
6849                    }
6850                }
6851            }
6852
6853            // Determine whether a hard keyboard is available and enabled.
6854            boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS;
6855            if (hardKeyboardAvailable != mHardKeyboardAvailable) {
6856                mHardKeyboardAvailable = hardKeyboardAvailable;
6857                mHardKeyboardEnabled = hardKeyboardAvailable;
6858                mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
6859                mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
6860            }
6861            if (!mHardKeyboardEnabled) {
6862                config.keyboard = Configuration.KEYBOARD_NOKEYS;
6863            }
6864
6865            // Let the policy update hidden states.
6866            config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
6867            config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
6868            config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO;
6869            mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence);
6870        }
6871
6872        return true;
6873    }
6874
6875    public boolean isHardKeyboardAvailable() {
6876        synchronized (mWindowMap) {
6877            return mHardKeyboardAvailable;
6878        }
6879    }
6880
6881    public boolean isHardKeyboardEnabled() {
6882        synchronized (mWindowMap) {
6883            return mHardKeyboardEnabled;
6884        }
6885    }
6886
6887    public void setHardKeyboardEnabled(boolean enabled) {
6888        synchronized (mWindowMap) {
6889            if (mHardKeyboardEnabled != enabled) {
6890                mHardKeyboardEnabled = enabled;
6891                mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
6892            }
6893        }
6894    }
6895
6896    public void setOnHardKeyboardStatusChangeListener(
6897            OnHardKeyboardStatusChangeListener listener) {
6898        synchronized (mWindowMap) {
6899            mHardKeyboardStatusChangeListener = listener;
6900        }
6901    }
6902
6903    void notifyHardKeyboardStatusChange() {
6904        final boolean available, enabled;
6905        final OnHardKeyboardStatusChangeListener listener;
6906        synchronized (mWindowMap) {
6907            listener = mHardKeyboardStatusChangeListener;
6908            available = mHardKeyboardAvailable;
6909            enabled = mHardKeyboardEnabled;
6910        }
6911        if (listener != null) {
6912            listener.onHardKeyboardStatusChange(available, enabled);
6913        }
6914    }
6915
6916    // -------------------------------------------------------------
6917    // Drag and drop
6918    // -------------------------------------------------------------
6919
6920    IBinder prepareDragSurface(IWindow window, SurfaceSession session,
6921            int flags, int width, int height, Surface outSurface) {
6922        if (DEBUG_DRAG) {
6923            Slog.d(TAG, "prepare drag surface: w=" + width + " h=" + height
6924                    + " flags=" + Integer.toHexString(flags) + " win=" + window
6925                    + " asbinder=" + window.asBinder());
6926        }
6927
6928        final int callerPid = Binder.getCallingPid();
6929        final long origId = Binder.clearCallingIdentity();
6930        IBinder token = null;
6931
6932        try {
6933            synchronized (mWindowMap) {
6934                try {
6935                    if (mDragState == null) {
6936                        // TODO(multi-display): support other displays
6937                        final DisplayContent displayContent = getDefaultDisplayContentLocked();
6938                        final Display display = displayContent.getDisplay();
6939                        SurfaceControl surface = new SurfaceControl(session, "drag surface",
6940                                width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
6941                        surface.setLayerStack(display.getLayerStack());
6942                        if (SHOW_TRANSACTIONS) Slog.i(TAG, "  DRAG "
6943                                + surface + ": CREATE");
6944                        outSurface.copyFrom(surface);
6945                        final IBinder winBinder = window.asBinder();
6946                        token = new Binder();
6947                        mDragState = new DragState(this, token, surface, /*flags*/ 0, winBinder);
6948                        token = mDragState.mToken = new Binder();
6949
6950                        // 5 second timeout for this window to actually begin the drag
6951                        mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder);
6952                        Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder);
6953                        mH.sendMessageDelayed(msg, 5000);
6954                    } else {
6955                        Slog.w(TAG, "Drag already in progress");
6956                    }
6957                } catch (OutOfResourcesException e) {
6958                    Slog.e(TAG, "Can't allocate drag surface w=" + width + " h=" + height, e);
6959                    if (mDragState != null) {
6960                        mDragState.reset();
6961                        mDragState = null;
6962                    }
6963                }
6964            }
6965        } finally {
6966            Binder.restoreCallingIdentity(origId);
6967        }
6968
6969        return token;
6970    }
6971
6972    // -------------------------------------------------------------
6973    // Input Events and Focus Management
6974    // -------------------------------------------------------------
6975
6976    final InputMonitor mInputMonitor = new InputMonitor(this);
6977    private boolean mEventDispatchingEnabled;
6978
6979    @Override
6980    public void pauseKeyDispatching(IBinder _token) {
6981        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
6982                "pauseKeyDispatching()")) {
6983            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
6984        }
6985
6986        synchronized (mWindowMap) {
6987            WindowToken token = mTokenMap.get(_token);
6988            if (token != null) {
6989                mInputMonitor.pauseDispatchingLw(token);
6990            }
6991        }
6992    }
6993
6994    @Override
6995    public void resumeKeyDispatching(IBinder _token) {
6996        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
6997                "resumeKeyDispatching()")) {
6998            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
6999        }
7000
7001        synchronized (mWindowMap) {
7002            WindowToken token = mTokenMap.get(_token);
7003            if (token != null) {
7004                mInputMonitor.resumeDispatchingLw(token);
7005            }
7006        }
7007    }
7008
7009    @Override
7010    public void setEventDispatching(boolean enabled) {
7011        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
7012                "setEventDispatching()")) {
7013            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
7014        }
7015
7016        synchronized (mWindowMap) {
7017            mEventDispatchingEnabled = enabled;
7018            if (mDisplayEnabled) {
7019                mInputMonitor.setEventDispatchingLw(enabled);
7020            }
7021        }
7022    }
7023
7024    private WindowState getFocusedWindow() {
7025        synchronized (mWindowMap) {
7026            return getFocusedWindowLocked();
7027        }
7028    }
7029
7030    private WindowState getFocusedWindowLocked() {
7031        return mCurrentFocus;
7032    }
7033
7034    public boolean detectSafeMode() {
7035        if (!mInputMonitor.waitForInputDevicesReady(
7036                INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) {
7037            Slog.w(TAG, "Devices still not ready after waiting "
7038                   + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS
7039                   + " milliseconds before attempting to detect safe mode.");
7040        }
7041
7042        int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
7043                KeyEvent.KEYCODE_MENU);
7044        int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S);
7045        int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD,
7046                KeyEvent.KEYCODE_DPAD_CENTER);
7047        int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL,
7048                InputManagerService.BTN_MOUSE);
7049        int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
7050                KeyEvent.KEYCODE_VOLUME_DOWN);
7051        mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0
7052                || volumeDownState > 0;
7053        try {
7054            if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0) {
7055                mSafeMode = true;
7056                SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, "");
7057            }
7058        } catch (IllegalArgumentException e) {
7059        }
7060        if (mSafeMode) {
7061            Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState
7062                    + " dpad=" + dpadState + " trackball=" + trackballState + ")");
7063        } else {
7064            Log.i(TAG, "SAFE MODE not enabled");
7065        }
7066        mPolicy.setSafeMode(mSafeMode);
7067        return mSafeMode;
7068    }
7069
7070    public void displayReady() {
7071        displayReady(Display.DEFAULT_DISPLAY);
7072
7073        synchronized(mWindowMap) {
7074            final DisplayContent displayContent = getDefaultDisplayContentLocked();
7075            readForcedDisplaySizeAndDensityLocked(displayContent);
7076            mDisplayReady = true;
7077        }
7078
7079        try {
7080            mActivityManager.updateConfiguration(null);
7081        } catch (RemoteException e) {
7082        }
7083
7084        synchronized(mWindowMap) {
7085            mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
7086                    PackageManager.FEATURE_TOUCHSCREEN);
7087            configureDisplayPolicyLocked(getDefaultDisplayContentLocked());
7088        }
7089
7090        try {
7091            mActivityManager.updateConfiguration(null);
7092        } catch (RemoteException e) {
7093        }
7094    }
7095
7096    private void displayReady(int displayId) {
7097        synchronized(mWindowMap) {
7098            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7099            if (displayContent != null) {
7100                mAnimator.addDisplayLocked(displayId);
7101                synchronized(displayContent.mDisplaySizeLock) {
7102                    // Bootstrap the default logical display from the display manager.
7103                    final DisplayInfo displayInfo = displayContent.getDisplayInfo();
7104                    DisplayInfo newDisplayInfo = mDisplayManagerInternal.getDisplayInfo(displayId);
7105                    if (newDisplayInfo != null) {
7106                        displayInfo.copyFrom(newDisplayInfo);
7107                    }
7108                    displayContent.mInitialDisplayWidth = displayInfo.logicalWidth;
7109                    displayContent.mInitialDisplayHeight = displayInfo.logicalHeight;
7110                    displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi;
7111                    displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth;
7112                    displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight;
7113                    displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity;
7114                    displayContent.mBaseDisplayRect.set(0, 0,
7115                            displayContent.mBaseDisplayWidth, displayContent.mBaseDisplayHeight);
7116                }
7117            }
7118        }
7119    }
7120
7121    public void systemReady() {
7122        mPolicy.systemReady();
7123    }
7124
7125    // -------------------------------------------------------------
7126    // Async Handler
7127    // -------------------------------------------------------------
7128
7129    final class H extends Handler {
7130        public static final int REPORT_FOCUS_CHANGE = 2;
7131        public static final int REPORT_LOSING_FOCUS = 3;
7132        public static final int DO_TRAVERSAL = 4;
7133        public static final int ADD_STARTING = 5;
7134        public static final int REMOVE_STARTING = 6;
7135        public static final int FINISHED_STARTING = 7;
7136        public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8;
7137        public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9;
7138        public static final int WINDOW_FREEZE_TIMEOUT = 11;
7139
7140        public static final int APP_TRANSITION_TIMEOUT = 13;
7141        public static final int PERSIST_ANIMATION_SCALE = 14;
7142        public static final int FORCE_GC = 15;
7143        public static final int ENABLE_SCREEN = 16;
7144        public static final int APP_FREEZE_TIMEOUT = 17;
7145        public static final int SEND_NEW_CONFIGURATION = 18;
7146        public static final int REPORT_WINDOWS_CHANGE = 19;
7147        public static final int DRAG_START_TIMEOUT = 20;
7148        public static final int DRAG_END_TIMEOUT = 21;
7149        public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22;
7150        public static final int BOOT_TIMEOUT = 23;
7151        public static final int WAITING_FOR_DRAWN_TIMEOUT = 24;
7152        public static final int SHOW_STRICT_MODE_VIOLATION = 25;
7153        public static final int DO_ANIMATION_CALLBACK = 26;
7154
7155        public static final int DO_DISPLAY_ADDED = 27;
7156        public static final int DO_DISPLAY_REMOVED = 28;
7157        public static final int DO_DISPLAY_CHANGED = 29;
7158
7159        public static final int CLIENT_FREEZE_TIMEOUT = 30;
7160        public static final int TAP_OUTSIDE_STACK = 31;
7161        public static final int NOTIFY_ACTIVITY_DRAWN = 32;
7162
7163        public static final int SHOW_DISPLAY_MASK = 33;
7164
7165        @Override
7166        public void handleMessage(Message msg) {
7167            if (DEBUG_WINDOW_TRACE) {
7168                Slog.v(TAG, "handleMessage: entry what=" + msg.what);
7169            }
7170            switch (msg.what) {
7171                case REPORT_FOCUS_CHANGE: {
7172                    WindowState lastFocus;
7173                    WindowState newFocus;
7174
7175                    synchronized(mWindowMap) {
7176                        lastFocus = mLastFocus;
7177                        newFocus = mCurrentFocus;
7178                        if (lastFocus == newFocus) {
7179                            // Focus is not changing, so nothing to do.
7180                            return;
7181                        }
7182                        mLastFocus = newFocus;
7183                        if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Focus moving from " + lastFocus +
7184                                " to " + newFocus);
7185                        if (newFocus != null && lastFocus != null
7186                                && !newFocus.isDisplayedLw()) {
7187                            //Slog.i(TAG, "Delaying loss of focus...");
7188                            mLosingFocus.add(lastFocus);
7189                            lastFocus = null;
7190                        }
7191                    }
7192
7193                    //System.out.println("Changing focus from " + lastFocus
7194                    //                   + " to " + newFocus);
7195                    if (newFocus != null) {
7196                        if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Gaining focus: " + newFocus);
7197                        newFocus.reportFocusChangedSerialized(true, mInTouchMode);
7198                        notifyFocusChanged();
7199                    }
7200
7201                    if (lastFocus != null) {
7202                        if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing focus: " + lastFocus);
7203                        lastFocus.reportFocusChangedSerialized(false, mInTouchMode);
7204                    }
7205                } break;
7206
7207                case REPORT_LOSING_FOCUS: {
7208                    ArrayList<WindowState> losers;
7209
7210                    synchronized(mWindowMap) {
7211                        losers = mLosingFocus;
7212                        mLosingFocus = new ArrayList<WindowState>();
7213                    }
7214
7215                    final int N = losers.size();
7216                    for (int i=0; i<N; i++) {
7217                        if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing delayed focus: " +
7218                                losers.get(i));
7219                        losers.get(i).reportFocusChangedSerialized(false, mInTouchMode);
7220                    }
7221                } break;
7222
7223                case DO_TRAVERSAL: {
7224                    synchronized(mWindowMap) {
7225                        mTraversalScheduled = false;
7226                        performLayoutAndPlaceSurfacesLocked();
7227                    }
7228                } break;
7229
7230                case ADD_STARTING: {
7231                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7232                    final StartingData sd = wtoken.startingData;
7233
7234                    if (sd == null) {
7235                        // Animation has been canceled... do nothing.
7236                        return;
7237                    }
7238
7239                    if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting "
7240                            + wtoken + ": pkg=" + sd.pkg);
7241
7242                    View view = null;
7243                    try {
7244                        view = mPolicy.addStartingWindow(
7245                            wtoken.token, sd.pkg, sd.theme, sd.compatInfo,
7246                            sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo, sd.windowFlags);
7247                    } catch (Exception e) {
7248                        Slog.w(TAG, "Exception when adding starting window", e);
7249                    }
7250
7251                    if (view != null) {
7252                        boolean abort = false;
7253
7254                        synchronized(mWindowMap) {
7255                            if (wtoken.removed || wtoken.startingData == null) {
7256                                // If the window was successfully added, then
7257                                // we need to remove it.
7258                                if (wtoken.startingWindow != null) {
7259                                    if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
7260                                            "Aborted starting " + wtoken
7261                                            + ": removed=" + wtoken.removed
7262                                            + " startingData=" + wtoken.startingData);
7263                                    wtoken.startingWindow = null;
7264                                    wtoken.startingData = null;
7265                                    abort = true;
7266                                }
7267                            } else {
7268                                wtoken.startingView = view;
7269                            }
7270                            if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG,
7271                                    "Added starting " + wtoken
7272                                    + ": startingWindow="
7273                                    + wtoken.startingWindow + " startingView="
7274                                    + wtoken.startingView);
7275                        }
7276
7277                        if (abort) {
7278                            try {
7279                                mPolicy.removeStartingWindow(wtoken.token, view);
7280                            } catch (Exception e) {
7281                                Slog.w(TAG, "Exception when removing starting window", e);
7282                            }
7283                        }
7284                    }
7285                } break;
7286
7287                case REMOVE_STARTING: {
7288                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7289                    IBinder token = null;
7290                    View view = null;
7291                    synchronized (mWindowMap) {
7292                        if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting "
7293                                + wtoken + ": startingWindow="
7294                                + wtoken.startingWindow + " startingView="
7295                                + wtoken.startingView);
7296                        if (wtoken.startingWindow != null) {
7297                            view = wtoken.startingView;
7298                            token = wtoken.token;
7299                            wtoken.startingData = null;
7300                            wtoken.startingView = null;
7301                            wtoken.startingWindow = null;
7302                            wtoken.startingDisplayed = false;
7303                        }
7304                    }
7305                    if (view != null) {
7306                        try {
7307                            mPolicy.removeStartingWindow(token, view);
7308                        } catch (Exception e) {
7309                            Slog.w(TAG, "Exception when removing starting window", e);
7310                        }
7311                    }
7312                } break;
7313
7314                case FINISHED_STARTING: {
7315                    IBinder token = null;
7316                    View view = null;
7317                    while (true) {
7318                        synchronized (mWindowMap) {
7319                            final int N = mFinishedStarting.size();
7320                            if (N <= 0) {
7321                                break;
7322                            }
7323                            AppWindowToken wtoken = mFinishedStarting.remove(N-1);
7324
7325                            if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
7326                                    "Finished starting " + wtoken
7327                                    + ": startingWindow=" + wtoken.startingWindow
7328                                    + " startingView=" + wtoken.startingView);
7329
7330                            if (wtoken.startingWindow == null) {
7331                                continue;
7332                            }
7333
7334                            view = wtoken.startingView;
7335                            token = wtoken.token;
7336                            wtoken.startingData = null;
7337                            wtoken.startingView = null;
7338                            wtoken.startingWindow = null;
7339                            wtoken.startingDisplayed = false;
7340                        }
7341
7342                        try {
7343                            mPolicy.removeStartingWindow(token, view);
7344                        } catch (Exception e) {
7345                            Slog.w(TAG, "Exception when removing starting window", e);
7346                        }
7347                    }
7348                } break;
7349
7350                case REPORT_APPLICATION_TOKEN_DRAWN: {
7351                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7352
7353                    try {
7354                        if (DEBUG_VISIBILITY) Slog.v(
7355                                TAG, "Reporting drawn in " + wtoken);
7356                        wtoken.appToken.windowsDrawn();
7357                    } catch (RemoteException ex) {
7358                    }
7359                } break;
7360
7361                case REPORT_APPLICATION_TOKEN_WINDOWS: {
7362                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7363
7364                    boolean nowVisible = msg.arg1 != 0;
7365                    boolean nowGone = msg.arg2 != 0;
7366
7367                    try {
7368                        if (DEBUG_VISIBILITY) Slog.v(
7369                                TAG, "Reporting visible in " + wtoken
7370                                + " visible=" + nowVisible
7371                                + " gone=" + nowGone);
7372                        if (nowVisible) {
7373                            wtoken.appToken.windowsVisible();
7374                        } else {
7375                            wtoken.appToken.windowsGone();
7376                        }
7377                    } catch (RemoteException ex) {
7378                    }
7379                } break;
7380
7381                case WINDOW_FREEZE_TIMEOUT: {
7382                    // TODO(multidisplay): Can non-default displays rotate?
7383                    synchronized (mWindowMap) {
7384                        Slog.w(TAG, "Window freeze timeout expired.");
7385                        final WindowList windows = getDefaultWindowListLocked();
7386                        int i = windows.size();
7387                        while (i > 0) {
7388                            i--;
7389                            WindowState w = windows.get(i);
7390                            if (w.mOrientationChanging) {
7391                                w.mOrientationChanging = false;
7392                                w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
7393                                        - mDisplayFreezeTime);
7394                                Slog.w(TAG, "Force clearing orientation change: " + w);
7395                            }
7396                        }
7397                        performLayoutAndPlaceSurfacesLocked();
7398                    }
7399                    break;
7400                }
7401
7402                case APP_TRANSITION_TIMEOUT: {
7403                    synchronized (mWindowMap) {
7404                        if (mAppTransition.isTransitionSet()) {
7405                            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** APP TRANSITION TIMEOUT");
7406                            mAppTransition.setTimeout();
7407                            performLayoutAndPlaceSurfacesLocked();
7408                        }
7409                    }
7410                    break;
7411                }
7412
7413                case PERSIST_ANIMATION_SCALE: {
7414                    Settings.Global.putFloat(mContext.getContentResolver(),
7415                            Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
7416                    Settings.Global.putFloat(mContext.getContentResolver(),
7417                            Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
7418                    Settings.Global.putFloat(mContext.getContentResolver(),
7419                            Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScale);
7420                    break;
7421                }
7422
7423                case FORCE_GC: {
7424                    synchronized (mWindowMap) {
7425                        // Since we're holding both mWindowMap and mAnimator we don't need to
7426                        // hold mAnimator.mLayoutToAnim.
7427                        if (mAnimator.mAnimating || mAnimationScheduled) {
7428                            // If we are animating, don't do the gc now but
7429                            // delay a bit so we don't interrupt the animation.
7430                            sendEmptyMessageDelayed(H.FORCE_GC, 2000);
7431                            return;
7432                        }
7433                        // If we are currently rotating the display, it will
7434                        // schedule a new message when done.
7435                        if (mDisplayFrozen) {
7436                            return;
7437                        }
7438                    }
7439                    Runtime.getRuntime().gc();
7440                    break;
7441                }
7442
7443                case ENABLE_SCREEN: {
7444                    performEnableScreen();
7445                    break;
7446                }
7447
7448                case APP_FREEZE_TIMEOUT: {
7449                    synchronized (mWindowMap) {
7450                        Slog.w(TAG, "App freeze timeout expired.");
7451                        final int numStacks = mStackIdToStack.size();
7452                        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
7453                            final TaskStack stack = mStackIdToStack.valueAt(stackNdx);
7454                            final ArrayList<Task> tasks = stack.getTasks();
7455                            for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
7456                                AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
7457                                for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
7458                                    AppWindowToken tok = tokens.get(tokenNdx);
7459                                    if (tok.mAppAnimator.freezingScreen) {
7460                                        Slog.w(TAG, "Force clearing freeze: " + tok);
7461                                        unsetAppFreezingScreenLocked(tok, true, true);
7462                                    }
7463                                }
7464                            }
7465                        }
7466                    }
7467                    break;
7468                }
7469
7470                case CLIENT_FREEZE_TIMEOUT: {
7471                    synchronized (mWindowMap) {
7472                        if (mClientFreezingScreen) {
7473                            mClientFreezingScreen = false;
7474                            mLastFinishedFreezeSource = "client-timeout";
7475                            stopFreezingDisplayLocked();
7476                        }
7477                    }
7478                    break;
7479                }
7480
7481                case SEND_NEW_CONFIGURATION: {
7482                    removeMessages(SEND_NEW_CONFIGURATION);
7483                    sendNewConfiguration();
7484                    break;
7485                }
7486
7487                case REPORT_WINDOWS_CHANGE: {
7488                    if (mWindowsChanged) {
7489                        synchronized (mWindowMap) {
7490                            mWindowsChanged = false;
7491                        }
7492                        notifyWindowsChanged();
7493                    }
7494                    break;
7495                }
7496
7497                case DRAG_START_TIMEOUT: {
7498                    IBinder win = (IBinder)msg.obj;
7499                    if (DEBUG_DRAG) {
7500                        Slog.w(TAG, "Timeout starting drag by win " + win);
7501                    }
7502                    synchronized (mWindowMap) {
7503                        // !!! TODO: ANR the app that has failed to start the drag in time
7504                        if (mDragState != null) {
7505                            mDragState.unregister();
7506                            mInputMonitor.updateInputWindowsLw(true /*force*/);
7507                            mDragState.reset();
7508                            mDragState = null;
7509                        }
7510                    }
7511                    break;
7512                }
7513
7514                case DRAG_END_TIMEOUT: {
7515                    IBinder win = (IBinder)msg.obj;
7516                    if (DEBUG_DRAG) {
7517                        Slog.w(TAG, "Timeout ending drag to win " + win);
7518                    }
7519                    synchronized (mWindowMap) {
7520                        // !!! TODO: ANR the drag-receiving app
7521                        if (mDragState != null) {
7522                            mDragState.mDragResult = false;
7523                            mDragState.endDragLw();
7524                        }
7525                    }
7526                    break;
7527                }
7528
7529                case REPORT_HARD_KEYBOARD_STATUS_CHANGE: {
7530                    notifyHardKeyboardStatusChange();
7531                    break;
7532                }
7533
7534                case BOOT_TIMEOUT: {
7535                    performBootTimeout();
7536                    break;
7537                }
7538
7539                case WAITING_FOR_DRAWN_TIMEOUT: {
7540                    Pair<WindowState, IRemoteCallback> pair;
7541                    synchronized (mWindowMap) {
7542                        pair = (Pair<WindowState, IRemoteCallback>)msg.obj;
7543                        Slog.w(TAG, "Timeout waiting for drawn: " + pair.first);
7544                        if (!mWaitingForDrawn.remove(pair)) {
7545                            return;
7546                        }
7547                    }
7548                    try {
7549                        pair.second.sendResult(null);
7550                    } catch (RemoteException e) {
7551                    }
7552                    break;
7553                }
7554
7555                case SHOW_STRICT_MODE_VIOLATION: {
7556                    showStrictModeViolation(msg.arg1, msg.arg2);
7557                    break;
7558                }
7559
7560                case SHOW_DISPLAY_MASK: {
7561                    showCircularMask();
7562                    break;
7563                }
7564
7565                case DO_ANIMATION_CALLBACK: {
7566                    try {
7567                        ((IRemoteCallback)msg.obj).sendResult(null);
7568                    } catch (RemoteException e) {
7569                    }
7570                    break;
7571                }
7572
7573                case DO_DISPLAY_ADDED:
7574                    handleDisplayAdded(msg.arg1);
7575                    break;
7576
7577                case DO_DISPLAY_REMOVED:
7578                    synchronized (mWindowMap) {
7579                        handleDisplayRemovedLocked(msg.arg1);
7580                    }
7581                    break;
7582
7583                case DO_DISPLAY_CHANGED:
7584                    synchronized (mWindowMap) {
7585                        handleDisplayChangedLocked(msg.arg1);
7586                    }
7587                    break;
7588
7589                case TAP_OUTSIDE_STACK: {
7590                    int stackId;
7591                    synchronized (mWindowMap) {
7592                        stackId = ((DisplayContent)msg.obj).stackIdFromPoint(msg.arg1, msg.arg2);
7593                    }
7594                    if (stackId >= 0) {
7595                        try {
7596                            mActivityManager.setFocusedStack(stackId);
7597                        } catch (RemoteException e) {
7598                        }
7599                    }
7600                }
7601                break;
7602                case NOTIFY_ACTIVITY_DRAWN:
7603                    try {
7604                        mActivityManager.notifyActivityDrawn((IBinder) msg.obj);
7605                    } catch (RemoteException e) {
7606                    }
7607                    break;
7608            }
7609            if (DEBUG_WINDOW_TRACE) {
7610                Slog.v(TAG, "handleMessage: exit");
7611            }
7612        }
7613    }
7614
7615    // -------------------------------------------------------------
7616    // IWindowManager API
7617    // -------------------------------------------------------------
7618
7619    @Override
7620    public IWindowSession openSession(IInputMethodClient client,
7621            IInputContext inputContext) {
7622        if (client == null) throw new IllegalArgumentException("null client");
7623        if (inputContext == null) throw new IllegalArgumentException("null inputContext");
7624        Session session = new Session(this, client, inputContext);
7625        return session;
7626    }
7627
7628    @Override
7629    public boolean inputMethodClientHasFocus(IInputMethodClient client) {
7630        synchronized (mWindowMap) {
7631            // The focus for the client is the window immediately below
7632            // where we would place the input method window.
7633            int idx = findDesiredInputMethodWindowIndexLocked(false);
7634            if (idx > 0) {
7635                // TODO(multidisplay): IMEs are only supported on the default display.
7636                WindowState imFocus = getDefaultWindowListLocked().get(idx-1);
7637                if (DEBUG_INPUT_METHOD) {
7638                    Slog.i(TAG, "Desired input method target: " + imFocus);
7639                    Slog.i(TAG, "Current focus: " + mCurrentFocus);
7640                    Slog.i(TAG, "Last focus: " + mLastFocus);
7641                }
7642                if (imFocus != null) {
7643                    // This may be a starting window, in which case we still want
7644                    // to count it as okay.
7645                    if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING
7646                            && imFocus.mAppToken != null) {
7647                        // The client has definitely started, so it really should
7648                        // have a window in this app token.  Let's look for it.
7649                        for (int i=0; i<imFocus.mAppToken.windows.size(); i++) {
7650                            WindowState w = imFocus.mAppToken.windows.get(i);
7651                            if (w != imFocus) {
7652                                Log.i(TAG, "Switching to real app window: " + w);
7653                                imFocus = w;
7654                                break;
7655                            }
7656                        }
7657                    }
7658                    if (DEBUG_INPUT_METHOD) {
7659                        Slog.i(TAG, "IM target client: " + imFocus.mSession.mClient);
7660                        if (imFocus.mSession.mClient != null) {
7661                            Slog.i(TAG, "IM target client binder: "
7662                                    + imFocus.mSession.mClient.asBinder());
7663                            Slog.i(TAG, "Requesting client binder: " + client.asBinder());
7664                        }
7665                    }
7666                    if (imFocus.mSession.mClient != null &&
7667                            imFocus.mSession.mClient.asBinder() == client.asBinder()) {
7668                        return true;
7669                    }
7670                }
7671            }
7672
7673            // Okay, how about this...  what is the current focus?
7674            // It seems in some cases we may not have moved the IM
7675            // target window, such as when it was in a pop-up window,
7676            // so let's also look at the current focus.  (An example:
7677            // go to Gmail, start searching so the keyboard goes up,
7678            // press home.  Sometimes the IME won't go down.)
7679            // Would be nice to fix this more correctly, but it's
7680            // way at the end of a release, and this should be good enough.
7681            if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null
7682                    && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) {
7683                return true;
7684            }
7685        }
7686        return false;
7687    }
7688
7689    @Override
7690    public void getInitialDisplaySize(int displayId, Point size) {
7691        synchronized (mWindowMap) {
7692            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7693            if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
7694                synchronized(displayContent.mDisplaySizeLock) {
7695                    size.x = displayContent.mInitialDisplayWidth;
7696                    size.y = displayContent.mInitialDisplayHeight;
7697                }
7698            }
7699        }
7700    }
7701
7702    @Override
7703    public void getBaseDisplaySize(int displayId, Point size) {
7704        synchronized (mWindowMap) {
7705            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7706            if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
7707                synchronized(displayContent.mDisplaySizeLock) {
7708                    size.x = displayContent.mBaseDisplayWidth;
7709                    size.y = displayContent.mBaseDisplayHeight;
7710                }
7711            }
7712        }
7713    }
7714
7715    @Override
7716    public void setForcedDisplaySize(int displayId, int width, int height) {
7717        if (mContext.checkCallingOrSelfPermission(
7718                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7719                PackageManager.PERMISSION_GRANTED) {
7720            throw new SecurityException("Must hold permission " +
7721                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
7722        }
7723        if (displayId != Display.DEFAULT_DISPLAY) {
7724            throw new IllegalArgumentException("Can only set the default display");
7725        }
7726        final long ident = Binder.clearCallingIdentity();
7727        try {
7728            synchronized(mWindowMap) {
7729                // Set some sort of reasonable bounds on the size of the display that we
7730                // will try to emulate.
7731                final int MIN_WIDTH = 200;
7732                final int MIN_HEIGHT = 200;
7733                final int MAX_SCALE = 2;
7734                final DisplayContent displayContent = getDisplayContentLocked(displayId);
7735                if (displayContent != null) {
7736                    width = Math.min(Math.max(width, MIN_WIDTH),
7737                            displayContent.mInitialDisplayWidth * MAX_SCALE);
7738                    height = Math.min(Math.max(height, MIN_HEIGHT),
7739                            displayContent.mInitialDisplayHeight * MAX_SCALE);
7740                    setForcedDisplaySizeLocked(displayContent, width, height);
7741                    Settings.Global.putString(mContext.getContentResolver(),
7742                            Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height);
7743                }
7744            }
7745        } finally {
7746            Binder.restoreCallingIdentity(ident);
7747        }
7748    }
7749
7750    private void readForcedDisplaySizeAndDensityLocked(final DisplayContent displayContent) {
7751        String sizeStr = Settings.Global.getString(mContext.getContentResolver(),
7752                Settings.Global.DISPLAY_SIZE_FORCED);
7753        if (sizeStr == null || sizeStr.length() == 0) {
7754            sizeStr = SystemProperties.get(SIZE_OVERRIDE, null);
7755        }
7756        if (sizeStr != null && sizeStr.length() > 0) {
7757            final int pos = sizeStr.indexOf(',');
7758            if (pos > 0 && sizeStr.lastIndexOf(',') == pos) {
7759                int width, height;
7760                try {
7761                    width = Integer.parseInt(sizeStr.substring(0, pos));
7762                    height = Integer.parseInt(sizeStr.substring(pos+1));
7763                    synchronized(displayContent.mDisplaySizeLock) {
7764                        if (displayContent.mBaseDisplayWidth != width
7765                                || displayContent.mBaseDisplayHeight != height) {
7766                            Slog.i(TAG, "FORCED DISPLAY SIZE: " + width + "x" + height);
7767                            displayContent.mBaseDisplayWidth = width;
7768                            displayContent.mBaseDisplayHeight = height;
7769                        }
7770                    }
7771                } catch (NumberFormatException ex) {
7772                }
7773            }
7774        }
7775        String densityStr = Settings.Global.getString(mContext.getContentResolver(),
7776                Settings.Global.DISPLAY_DENSITY_FORCED);
7777        if (densityStr == null || densityStr.length() == 0) {
7778            densityStr = SystemProperties.get(DENSITY_OVERRIDE, null);
7779        }
7780        if (densityStr != null && densityStr.length() > 0) {
7781            int density;
7782            try {
7783                density = Integer.parseInt(densityStr);
7784                synchronized(displayContent.mDisplaySizeLock) {
7785                    if (displayContent.mBaseDisplayDensity != density) {
7786                        Slog.i(TAG, "FORCED DISPLAY DENSITY: " + density);
7787                        displayContent.mBaseDisplayDensity = density;
7788                    }
7789                }
7790            } catch (NumberFormatException ex) {
7791            }
7792        }
7793    }
7794
7795    // displayContent must not be null
7796    private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {
7797        Slog.i(TAG, "Using new display size: " + width + "x" + height);
7798
7799        synchronized(displayContent.mDisplaySizeLock) {
7800            displayContent.mBaseDisplayWidth = width;
7801            displayContent.mBaseDisplayHeight = height;
7802        }
7803        reconfigureDisplayLocked(displayContent);
7804    }
7805
7806    @Override
7807    public void clearForcedDisplaySize(int displayId) {
7808        if (mContext.checkCallingOrSelfPermission(
7809                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7810                PackageManager.PERMISSION_GRANTED) {
7811            throw new SecurityException("Must hold permission " +
7812                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
7813        }
7814        if (displayId != Display.DEFAULT_DISPLAY) {
7815            throw new IllegalArgumentException("Can only set the default display");
7816        }
7817        final long ident = Binder.clearCallingIdentity();
7818        try {
7819            synchronized(mWindowMap) {
7820                final DisplayContent displayContent = getDisplayContentLocked(displayId);
7821                if (displayContent != null) {
7822                    setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
7823                            displayContent.mInitialDisplayHeight);
7824                    Settings.Global.putString(mContext.getContentResolver(),
7825                            Settings.Global.DISPLAY_SIZE_FORCED, "");
7826                }
7827            }
7828        } finally {
7829            Binder.restoreCallingIdentity(ident);
7830        }
7831    }
7832
7833    @Override
7834    public int getInitialDisplayDensity(int displayId) {
7835        synchronized (mWindowMap) {
7836            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7837            if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
7838                synchronized(displayContent.mDisplaySizeLock) {
7839                    return displayContent.mInitialDisplayDensity;
7840                }
7841            }
7842        }
7843        return -1;
7844    }
7845
7846    @Override
7847    public int getBaseDisplayDensity(int displayId) {
7848        synchronized (mWindowMap) {
7849            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7850            if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
7851                synchronized(displayContent.mDisplaySizeLock) {
7852                    return displayContent.mBaseDisplayDensity;
7853                }
7854            }
7855        }
7856        return -1;
7857    }
7858
7859    @Override
7860    public void setForcedDisplayDensity(int displayId, int density) {
7861        if (mContext.checkCallingOrSelfPermission(
7862                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7863                PackageManager.PERMISSION_GRANTED) {
7864            throw new SecurityException("Must hold permission " +
7865                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
7866        }
7867        if (displayId != Display.DEFAULT_DISPLAY) {
7868            throw new IllegalArgumentException("Can only set the default display");
7869        }
7870        final long ident = Binder.clearCallingIdentity();
7871        try {
7872            synchronized(mWindowMap) {
7873                final DisplayContent displayContent = getDisplayContentLocked(displayId);
7874                if (displayContent != null) {
7875                    setForcedDisplayDensityLocked(displayContent, density);
7876                    Settings.Global.putString(mContext.getContentResolver(),
7877                            Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density));
7878                }
7879            }
7880        } finally {
7881            Binder.restoreCallingIdentity(ident);
7882        }
7883    }
7884
7885    // displayContent must not be null
7886    private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) {
7887        Slog.i(TAG, "Using new display density: " + density);
7888
7889        synchronized(displayContent.mDisplaySizeLock) {
7890            displayContent.mBaseDisplayDensity = density;
7891        }
7892        reconfigureDisplayLocked(displayContent);
7893    }
7894
7895    @Override
7896    public void clearForcedDisplayDensity(int displayId) {
7897        if (mContext.checkCallingOrSelfPermission(
7898                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7899                PackageManager.PERMISSION_GRANTED) {
7900            throw new SecurityException("Must hold permission " +
7901                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
7902        }
7903        if (displayId != Display.DEFAULT_DISPLAY) {
7904            throw new IllegalArgumentException("Can only set the default display");
7905        }
7906        final long ident = Binder.clearCallingIdentity();
7907        try {
7908            synchronized(mWindowMap) {
7909                final DisplayContent displayContent = getDisplayContentLocked(displayId);
7910                if (displayContent != null) {
7911                    setForcedDisplayDensityLocked(displayContent,
7912                            displayContent.mInitialDisplayDensity);
7913                    Settings.Global.putString(mContext.getContentResolver(),
7914                            Settings.Global.DISPLAY_DENSITY_FORCED, "");
7915                }
7916            }
7917        } finally {
7918            Binder.restoreCallingIdentity(ident);
7919        }
7920    }
7921
7922    // displayContent must not be null
7923    private void reconfigureDisplayLocked(DisplayContent displayContent) {
7924        // TODO: Multidisplay: for now only use with default display.
7925        configureDisplayPolicyLocked(displayContent);
7926        displayContent.layoutNeeded = true;
7927
7928        boolean configChanged = updateOrientationFromAppTokensLocked(false);
7929        mTempConfiguration.setToDefaults();
7930        mTempConfiguration.fontScale = mCurConfiguration.fontScale;
7931        if (computeScreenConfigurationLocked(mTempConfiguration)) {
7932            if (mCurConfiguration.diff(mTempConfiguration) != 0) {
7933                configChanged = true;
7934            }
7935        }
7936
7937        if (configChanged) {
7938            mWaitingForConfig = true;
7939            startFreezingDisplayLocked(false, 0, 0);
7940            mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
7941        }
7942
7943        performLayoutAndPlaceSurfacesLocked();
7944    }
7945
7946    private void configureDisplayPolicyLocked(DisplayContent displayContent) {
7947        mPolicy.setInitialDisplaySize(displayContent.getDisplay(),
7948                displayContent.mBaseDisplayWidth,
7949                displayContent.mBaseDisplayHeight,
7950                displayContent.mBaseDisplayDensity);
7951
7952        DisplayInfo displayInfo = displayContent.getDisplayInfo();
7953        mPolicy.setDisplayOverscan(displayContent.getDisplay(),
7954                displayInfo.overscanLeft, displayInfo.overscanTop,
7955                displayInfo.overscanRight, displayInfo.overscanBottom);
7956    }
7957
7958    @Override
7959    public void setOverscan(int displayId, int left, int top, int right, int bottom) {
7960        if (mContext.checkCallingOrSelfPermission(
7961                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7962                PackageManager.PERMISSION_GRANTED) {
7963            throw new SecurityException("Must hold permission " +
7964                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
7965        }
7966        final long ident = Binder.clearCallingIdentity();
7967        try {
7968            synchronized(mWindowMap) {
7969                DisplayContent displayContent = getDisplayContentLocked(displayId);
7970                if (displayContent != null) {
7971                    setOverscanLocked(displayContent, left, top, right, bottom);
7972                }
7973            }
7974        } finally {
7975            Binder.restoreCallingIdentity(ident);
7976        }
7977    }
7978
7979    private void setOverscanLocked(DisplayContent displayContent,
7980            int left, int top, int right, int bottom) {
7981        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
7982        synchronized (displayContent.mDisplaySizeLock) {
7983            displayInfo.overscanLeft = left;
7984            displayInfo.overscanTop = top;
7985            displayInfo.overscanRight = right;
7986            displayInfo.overscanBottom = bottom;
7987        }
7988
7989        mDisplaySettings.setOverscanLocked(displayInfo.name, left, top, right, bottom);
7990        mDisplaySettings.writeSettingsLocked();
7991
7992        reconfigureDisplayLocked(displayContent);
7993    }
7994
7995    // -------------------------------------------------------------
7996    // Internals
7997    // -------------------------------------------------------------
7998
7999    final WindowState windowForClientLocked(Session session, IWindow client,
8000            boolean throwOnError) {
8001        return windowForClientLocked(session, client.asBinder(), throwOnError);
8002    }
8003
8004    final WindowState windowForClientLocked(Session session, IBinder client,
8005            boolean throwOnError) {
8006        WindowState win = mWindowMap.get(client);
8007        if (localLOGV) Slog.v(
8008            TAG, "Looking up client " + client + ": " + win);
8009        if (win == null) {
8010            RuntimeException ex = new IllegalArgumentException(
8011                    "Requested window " + client + " does not exist");
8012            if (throwOnError) {
8013                throw ex;
8014            }
8015            Slog.w(TAG, "Failed looking up window", ex);
8016            return null;
8017        }
8018        if (session != null && win.mSession != session) {
8019            RuntimeException ex = new IllegalArgumentException(
8020                    "Requested window " + client + " is in session " +
8021                    win.mSession + ", not " + session);
8022            if (throwOnError) {
8023                throw ex;
8024            }
8025            Slog.w(TAG, "Failed looking up window", ex);
8026            return null;
8027        }
8028
8029        return win;
8030    }
8031
8032    final void rebuildAppWindowListLocked() {
8033        rebuildAppWindowListLocked(getDefaultDisplayContentLocked());
8034    }
8035
8036    private void rebuildAppWindowListLocked(final DisplayContent displayContent) {
8037        final WindowList windows = displayContent.getWindowList();
8038        int NW = windows.size();
8039        int i;
8040        int lastBelow = -1;
8041        int numRemoved = 0;
8042
8043        if (mRebuildTmp.length < NW) {
8044            mRebuildTmp = new WindowState[NW+10];
8045        }
8046
8047        // First remove all existing app windows.
8048        i=0;
8049        while (i < NW) {
8050            WindowState w = windows.get(i);
8051            if (w.mAppToken != null) {
8052                WindowState win = windows.remove(i);
8053                win.mRebuilding = true;
8054                mRebuildTmp[numRemoved] = win;
8055                mWindowsChanged = true;
8056                if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Rebuild removing window: " + win);
8057                NW--;
8058                numRemoved++;
8059                continue;
8060            } else if (lastBelow == i-1) {
8061                if (w.mAttrs.type == TYPE_WALLPAPER || w.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
8062                    lastBelow = i;
8063                }
8064            }
8065            i++;
8066        }
8067
8068        // Keep whatever windows were below the app windows still below,
8069        // by skipping them.
8070        lastBelow++;
8071        i = lastBelow;
8072
8073        // First add all of the exiting app tokens...  these are no longer
8074        // in the main app list, but still have windows shown.  We put them
8075        // in the back because now that the animation is over we no longer
8076        // will care about them.
8077        final ArrayList<TaskStack> stacks = displayContent.getStacks();
8078        final int numStacks = stacks.size();
8079        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
8080            AppTokenList exitingAppTokens = stacks.get(stackNdx).mExitingAppTokens;
8081            int NT = exitingAppTokens.size();
8082            for (int j = 0; j < NT; j++) {
8083                i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j));
8084            }
8085        }
8086
8087        // And add in the still active app tokens in Z order.
8088        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
8089            final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
8090            final int numTasks = tasks.size();
8091            for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
8092                final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
8093                final int numTokens = tokens.size();
8094                for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
8095                    final AppWindowToken wtoken = tokens.get(tokenNdx);
8096                    if (wtoken.mDeferRemoval) {
8097                        continue;
8098                    }
8099                    i = reAddAppWindowsLocked(displayContent, i, wtoken);
8100                }
8101            }
8102        }
8103
8104        i -= lastBelow;
8105        if (i != numRemoved) {
8106            Slog.w(TAG, "On display=" + displayContent.getDisplayId() + " Rebuild removed " +
8107                    numRemoved + " windows but added " + i,
8108                    new RuntimeException("here").fillInStackTrace());
8109            for (i=0; i<numRemoved; i++) {
8110                WindowState ws = mRebuildTmp[i];
8111                if (ws.mRebuilding) {
8112                    StringWriter sw = new StringWriter();
8113                    PrintWriter pw = new FastPrintWriter(sw, false, 1024);
8114                    ws.dump(pw, "", true);
8115                    pw.flush();
8116                    Slog.w(TAG, "This window was lost: " + ws);
8117                    Slog.w(TAG, sw.toString());
8118                    ws.mWinAnimator.destroySurfaceLocked();
8119                }
8120            }
8121            Slog.w(TAG, "Current app token list:");
8122            dumpAppTokensLocked();
8123            Slog.w(TAG, "Final window list:");
8124            dumpWindowsLocked();
8125        }
8126    }
8127
8128    private final void assignLayersLocked(WindowList windows) {
8129        int N = windows.size();
8130        int curBaseLayer = 0;
8131        int curLayer = 0;
8132        int i;
8133
8134        if (DEBUG_LAYERS) Slog.v(TAG, "Assigning layers based on windows=" + windows,
8135                new RuntimeException("here").fillInStackTrace());
8136
8137        boolean anyLayerChanged = false;
8138
8139        for (i=0; i<N; i++) {
8140            final WindowState w = windows.get(i);
8141            final WindowStateAnimator winAnimator = w.mWinAnimator;
8142            boolean layerChanged = false;
8143            int oldLayer = w.mLayer;
8144            if (w.mBaseLayer == curBaseLayer || w.mIsImWindow
8145                    || (i > 0 && w.mIsWallpaper)) {
8146                curLayer += WINDOW_LAYER_MULTIPLIER;
8147                w.mLayer = curLayer;
8148            } else {
8149                curBaseLayer = curLayer = w.mBaseLayer;
8150                w.mLayer = curLayer;
8151            }
8152            if (w.mLayer != oldLayer) {
8153                layerChanged = true;
8154                anyLayerChanged = true;
8155            }
8156            final AppWindowToken wtoken = w.mAppToken;
8157            oldLayer = winAnimator.mAnimLayer;
8158            if (w.mTargetAppToken != null) {
8159                winAnimator.mAnimLayer =
8160                        w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment;
8161            } else if (wtoken != null) {
8162                winAnimator.mAnimLayer =
8163                        w.mLayer + wtoken.mAppAnimator.animLayerAdjustment;
8164            } else {
8165                winAnimator.mAnimLayer = w.mLayer;
8166            }
8167            if (w.mIsImWindow) {
8168                winAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment;
8169            } else if (w.mIsWallpaper) {
8170                winAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment;
8171            }
8172            if (winAnimator.mAnimLayer != oldLayer) {
8173                layerChanged = true;
8174                anyLayerChanged = true;
8175            }
8176            if (layerChanged && w.getStack().isDimming(winAnimator)) {
8177                // Force an animation pass just to update the mDimLayer layer.
8178                scheduleAnimationLocked();
8179            }
8180            if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": "
8181                    + "mBase=" + w.mBaseLayer
8182                    + " mLayer=" + w.mLayer
8183                    + (wtoken == null ?
8184                            "" : " mAppLayer=" + wtoken.mAppAnimator.animLayerAdjustment)
8185                    + " =mAnimLayer=" + winAnimator.mAnimLayer);
8186            //System.out.println(
8187            //    "Assigned layer " + curLayer + " to " + w.mClient.asBinder());
8188        }
8189
8190        //TODO (multidisplay): Magnification is supported only for the default display.
8191        if (mAccessibilityController != null && anyLayerChanged
8192                && windows.get(windows.size() - 1).getDisplayId() == Display.DEFAULT_DISPLAY) {
8193            mAccessibilityController.onWindowLayersChangedLocked();
8194        }
8195    }
8196
8197    private final void performLayoutAndPlaceSurfacesLocked() {
8198        int loopCount = 6;
8199        do {
8200            mTraversalScheduled = false;
8201            performLayoutAndPlaceSurfacesLockedLoop();
8202            mH.removeMessages(H.DO_TRAVERSAL);
8203            loopCount--;
8204        } while (mTraversalScheduled && loopCount > 0);
8205        mInnerFields.mWallpaperActionPending = false;
8206    }
8207
8208    private boolean mInLayout = false;
8209    private final void performLayoutAndPlaceSurfacesLockedLoop() {
8210        if (mInLayout) {
8211            if (DEBUG) {
8212                throw new RuntimeException("Recursive call!");
8213            }
8214            Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers="
8215                    + Debug.getCallers(3));
8216            return;
8217        }
8218
8219        if (mWaitingForConfig) {
8220            // Our configuration has changed (most likely rotation), but we
8221            // don't yet have the complete configuration to report to
8222            // applications.  Don't do any window layout until we have it.
8223            return;
8224        }
8225
8226        if (!mDisplayReady) {
8227            // Not yet initialized, nothing to do.
8228            return;
8229        }
8230
8231        Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout");
8232        mInLayout = true;
8233        boolean recoveringMemory = false;
8234
8235        try {
8236            if (mForceRemoves != null) {
8237                recoveringMemory = true;
8238                // Wait a little bit for things to settle down, and off we go.
8239                for (int i=0; i<mForceRemoves.size(); i++) {
8240                    WindowState ws = mForceRemoves.get(i);
8241                    Slog.i(TAG, "Force removing: " + ws);
8242                    removeWindowInnerLocked(ws.mSession, ws);
8243                }
8244                mForceRemoves = null;
8245                Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");
8246                Object tmp = new Object();
8247                synchronized (tmp) {
8248                    try {
8249                        tmp.wait(250);
8250                    } catch (InterruptedException e) {
8251                    }
8252                }
8253            }
8254        } catch (RuntimeException e) {
8255            Log.wtf(TAG, "Unhandled exception while force removing for memory", e);
8256        }
8257
8258        try {
8259            performLayoutAndPlaceSurfacesLockedInner(recoveringMemory);
8260
8261            mInLayout = false;
8262
8263            if (needsLayout()) {
8264                if (++mLayoutRepeatCount < 6) {
8265                    requestTraversalLocked();
8266                } else {
8267                    Slog.e(TAG, "Performed 6 layouts in a row. Skipping");
8268                    mLayoutRepeatCount = 0;
8269                }
8270            } else {
8271                mLayoutRepeatCount = 0;
8272            }
8273
8274            if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) {
8275                mH.removeMessages(H.REPORT_WINDOWS_CHANGE);
8276                mH.sendEmptyMessage(H.REPORT_WINDOWS_CHANGE);
8277            }
8278        } catch (RuntimeException e) {
8279            mInLayout = false;
8280            Log.wtf(TAG, "Unhandled exception while laying out windows", e);
8281        }
8282
8283        Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
8284    }
8285
8286    private final void performLayoutLockedInner(final DisplayContent displayContent,
8287                                    boolean initial, boolean updateInputWindows) {
8288        if (!displayContent.layoutNeeded) {
8289            return;
8290        }
8291        displayContent.layoutNeeded = false;
8292        WindowList windows = displayContent.getWindowList();
8293        boolean isDefaultDisplay = displayContent.isDefaultDisplay;
8294
8295        DisplayInfo displayInfo = displayContent.getDisplayInfo();
8296        final int dw = displayInfo.logicalWidth;
8297        final int dh = displayInfo.logicalHeight;
8298
8299        final int NFW = mFakeWindows.size();
8300        for (int i=0; i<NFW; i++) {
8301            mFakeWindows.get(i).layout(dw, dh);
8302        }
8303
8304        final int N = windows.size();
8305        int i;
8306
8307        if (DEBUG_LAYOUT) {
8308            Slog.v(TAG, "-------------------------------------");
8309            Slog.v(TAG, "performLayout: needed="
8310                    + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh);
8311        }
8312
8313        WindowStateAnimator universeBackground = null;
8314
8315        mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mRotation);
8316        if (isDefaultDisplay) {
8317            // Not needed on non-default displays.
8318            mSystemDecorLayer = mPolicy.getSystemDecorLayerLw();
8319            mScreenRect.set(0, 0, dw, dh);
8320        }
8321
8322        mPolicy.getContentRectLw(mTmpContentRect);
8323        displayContent.resize(mTmpContentRect);
8324
8325        int seq = mLayoutSeq+1;
8326        if (seq < 0) seq = 0;
8327        mLayoutSeq = seq;
8328
8329        boolean behindDream = false;
8330
8331        // First perform layout of any root windows (not attached
8332        // to another window).
8333        int topAttached = -1;
8334        for (i = N-1; i >= 0; i--) {
8335            final WindowState win = windows.get(i);
8336
8337            // Don't do layout of a window if it is not visible, or
8338            // soon won't be visible, to avoid wasting time and funky
8339            // changes while a window is animating away.
8340            final boolean gone = (behindDream && mPolicy.canBeForceHidden(win, win.mAttrs))
8341                    || win.isGoneForLayoutLw();
8342
8343            if (DEBUG_LAYOUT && !win.mLayoutAttached) {
8344                Slog.v(TAG, "1ST PASS " + win
8345                        + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame
8346                        + " mLayoutAttached=" + win.mLayoutAttached
8347                        + " screen changed=" + win.isConfigChanged());
8348                final AppWindowToken atoken = win.mAppToken;
8349                if (gone) Slog.v(TAG, "  GONE: mViewVisibility="
8350                        + win.mViewVisibility + " mRelayoutCalled="
8351                        + win.mRelayoutCalled + " hidden="
8352                        + win.mRootToken.hidden + " hiddenRequested="
8353                        + (atoken != null && atoken.hiddenRequested)
8354                        + " mAttachedHidden=" + win.mAttachedHidden);
8355                else Slog.v(TAG, "  VIS: mViewVisibility="
8356                        + win.mViewVisibility + " mRelayoutCalled="
8357                        + win.mRelayoutCalled + " hidden="
8358                        + win.mRootToken.hidden + " hiddenRequested="
8359                        + (atoken != null && atoken.hiddenRequested)
8360                        + " mAttachedHidden=" + win.mAttachedHidden);
8361            }
8362
8363            // If this view is GONE, then skip it -- keep the current
8364            // frame, and let the caller know so they can ignore it
8365            // if they want.  (We do the normal layout for INVISIBLE
8366            // windows, since that means "perform layout as normal,
8367            // just don't display").
8368            if (!gone || !win.mHaveFrame || win.mLayoutNeeded
8369                    || ((win.isConfigChanged() || win.setInsetsChanged()) &&
8370                            ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
8371                            win.mAppToken != null && win.mAppToken.layoutConfigChanges))
8372                    || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
8373                if (!win.mLayoutAttached) {
8374                    if (initial) {
8375                        //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
8376                        win.mContentChanged = false;
8377                    }
8378                    if (win.mAttrs.type == TYPE_DREAM) {
8379                        // Don't layout windows behind a dream, so that if it
8380                        // does stuff like hide the status bar we won't get a
8381                        // bad transition when it goes away.
8382                        behindDream = true;
8383                    }
8384                    win.mLayoutNeeded = false;
8385                    win.prelayout();
8386                    mPolicy.layoutWindowLw(win, win.mAttrs, null);
8387                    win.mLayoutSeq = seq;
8388                    if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame="
8389                            + win.mFrame + " mContainingFrame="
8390                            + win.mContainingFrame + " mDisplayFrame="
8391                            + win.mDisplayFrame);
8392                } else {
8393                    if (topAttached < 0) topAttached = i;
8394                }
8395            }
8396            if (win.mViewVisibility == View.VISIBLE
8397                    && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND
8398                    && universeBackground == null) {
8399                universeBackground = win.mWinAnimator;
8400            }
8401        }
8402
8403        if (mAnimator.mUniverseBackground  != universeBackground) {
8404            mFocusMayChange = true;
8405            mAnimator.mUniverseBackground = universeBackground;
8406        }
8407
8408        boolean attachedBehindDream = false;
8409
8410        // Now perform layout of attached windows, which usually
8411        // depend on the position of the window they are attached to.
8412        // XXX does not deal with windows that are attached to windows
8413        // that are themselves attached.
8414        for (i = topAttached; i >= 0; i--) {
8415            final WindowState win = windows.get(i);
8416
8417            if (win.mLayoutAttached) {
8418                if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win
8419                        + " mHaveFrame=" + win.mHaveFrame
8420                        + " mViewVisibility=" + win.mViewVisibility
8421                        + " mRelayoutCalled=" + win.mRelayoutCalled);
8422                // If this view is GONE, then skip it -- keep the current
8423                // frame, and let the caller know so they can ignore it
8424                // if they want.  (We do the normal layout for INVISIBLE
8425                // windows, since that means "perform layout as normal,
8426                // just don't display").
8427                if (attachedBehindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) {
8428                    continue;
8429                }
8430                if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled)
8431                        || !win.mHaveFrame || win.mLayoutNeeded) {
8432                    if (initial) {
8433                        //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
8434                        win.mContentChanged = false;
8435                    }
8436                    win.mLayoutNeeded = false;
8437                    win.prelayout();
8438                    mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow);
8439                    win.mLayoutSeq = seq;
8440                    if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame="
8441                            + win.mFrame + " mContainingFrame="
8442                            + win.mContainingFrame + " mDisplayFrame="
8443                            + win.mDisplayFrame);
8444                }
8445            } else if (win.mAttrs.type == TYPE_DREAM) {
8446                // Don't layout windows behind a dream, so that if it
8447                // does stuff like hide the status bar we won't get a
8448                // bad transition when it goes away.
8449                attachedBehindDream = behindDream;
8450            }
8451        }
8452
8453        // Window frames may have changed.  Tell the input dispatcher about it.
8454        mInputMonitor.setUpdateInputWindowsNeededLw();
8455        if (updateInputWindows) {
8456            mInputMonitor.updateInputWindowsLw(false /*force*/);
8457        }
8458
8459        mPolicy.finishLayoutLw();
8460    }
8461
8462    void makeWindowFreezingScreenIfNeededLocked(WindowState w) {
8463        // If the screen is currently frozen or off, then keep
8464        // it frozen/off until this window draws at its new
8465        // orientation.
8466        if (!okToDisplay()) {
8467            if (DEBUG_ORIENTATION) Slog.v(TAG, "Changing surface while display frozen: " + w);
8468            w.mOrientationChanging = true;
8469            w.mLastFreezeDuration = 0;
8470            mInnerFields.mOrientationChangeComplete = false;
8471            if (!mWindowsFreezingScreen) {
8472                mWindowsFreezingScreen = true;
8473                // XXX should probably keep timeout from
8474                // when we first froze the display.
8475                mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
8476                mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT,
8477                        WINDOW_FREEZE_TIMEOUT_DURATION);
8478            }
8479        }
8480    }
8481
8482    /**
8483     * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
8484     * @param windows List of windows on default display.
8485     * @return bitmap indicating if another pass through layout must be made.
8486     */
8487    public int handleAppTransitionReadyLocked(WindowList windows) {
8488        int changes = 0;
8489        int i;
8490        int NN = mOpeningApps.size();
8491        boolean goodToGo = true;
8492        if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8493                "Checking " + NN + " opening apps (frozen="
8494                + mDisplayFrozen + " timeout="
8495                + mAppTransition.isTimeout() + ")...");
8496        if (!mDisplayFrozen && !mAppTransition.isTimeout()) {
8497            // If the display isn't frozen, wait to do anything until
8498            // all of the apps are ready.  Otherwise just go because
8499            // we'll unfreeze the display when everyone is ready.
8500            for (i=0; i<NN && goodToGo; i++) {
8501                AppWindowToken wtoken = mOpeningApps.get(i);
8502                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8503                        "Check opening app=" + wtoken + ": allDrawn="
8504                        + wtoken.allDrawn + " startingDisplayed="
8505                        + wtoken.startingDisplayed + " startingMoved="
8506                        + wtoken.startingMoved);
8507                if (!wtoken.allDrawn && !wtoken.startingDisplayed
8508                        && !wtoken.startingMoved) {
8509                    goodToGo = false;
8510                }
8511            }
8512        }
8513        if (goodToGo) {
8514            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO");
8515            int transit = mAppTransition.getAppTransition();
8516            if (mSkipAppTransitionAnimation) {
8517                transit = AppTransition.TRANSIT_UNSET;
8518            }
8519            mAppTransition.goodToGo();
8520            mStartingIconInTransition = false;
8521            mSkipAppTransitionAnimation = false;
8522
8523            mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
8524
8525            rebuildAppWindowListLocked();
8526
8527            // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper
8528            WindowState oldWallpaper =
8529                    mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating()
8530                        && !mWallpaperTarget.mWinAnimator.isDummyAnimation()
8531                    ? null : mWallpaperTarget;
8532
8533            mInnerFields.mWallpaperMayChange = false;
8534
8535            // The top-most window will supply the layout params,
8536            // and we will determine it below.
8537            LayoutParams animLp = null;
8538            int bestAnimLayer = -1;
8539            boolean fullscreenAnim = false;
8540
8541            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8542                    "New wallpaper target=" + mWallpaperTarget
8543                    + ", oldWallpaper=" + oldWallpaper
8544                    + ", lower target=" + mLowerWallpaperTarget
8545                    + ", upper target=" + mUpperWallpaperTarget);
8546
8547            boolean openingAppHasWallpaper = false;
8548            boolean closingAppHasWallpaper = false;
8549            final AppWindowToken lowerWallpaperAppToken;
8550            final AppWindowToken upperWallpaperAppToken;
8551            if (mLowerWallpaperTarget == null) {
8552                lowerWallpaperAppToken = upperWallpaperAppToken = null;
8553            } else {
8554                lowerWallpaperAppToken = mLowerWallpaperTarget.mAppToken;
8555                upperWallpaperAppToken = mUpperWallpaperTarget.mAppToken;
8556            }
8557
8558            // Do a first pass through the tokens for two
8559            // things:
8560            // (1) Determine if both the closing and opening
8561            // app token sets are wallpaper targets, in which
8562            // case special animations are needed
8563            // (since the wallpaper needs to stay static
8564            // behind them).
8565            // (2) Find the layout params of the top-most
8566            // application window in the tokens, which is
8567            // what will control the animation theme.
8568            final int NC = mClosingApps.size();
8569            NN = NC + mOpeningApps.size();
8570            for (i=0; i<NN; i++) {
8571                final AppWindowToken wtoken;
8572                if (i < NC) {
8573                    wtoken = mClosingApps.get(i);
8574                    if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
8575                        closingAppHasWallpaper = true;
8576                    }
8577                } else {
8578                    wtoken = mOpeningApps.get(i - NC);
8579                    if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
8580                        openingAppHasWallpaper = true;
8581                    }
8582                }
8583
8584                if (wtoken.appFullscreen) {
8585                    WindowState ws = wtoken.findMainWindow();
8586                    if (ws != null) {
8587                        animLp = ws.mAttrs;
8588                        bestAnimLayer = ws.mLayer;
8589                        fullscreenAnim = true;
8590                    }
8591                } else if (!fullscreenAnim) {
8592                    WindowState ws = wtoken.findMainWindow();
8593                    if (ws != null) {
8594                        if (ws.mLayer > bestAnimLayer) {
8595                            animLp = ws.mAttrs;
8596                            bestAnimLayer = ws.mLayer;
8597                        }
8598                    }
8599                }
8600            }
8601
8602            mAnimateWallpaperWithTarget = false;
8603            if (closingAppHasWallpaper && openingAppHasWallpaper) {
8604                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!");
8605                switch (transit) {
8606                    case AppTransition.TRANSIT_ACTIVITY_OPEN:
8607                    case AppTransition.TRANSIT_TASK_OPEN:
8608                    case AppTransition.TRANSIT_TASK_TO_FRONT:
8609                        transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN;
8610                        break;
8611                    case AppTransition.TRANSIT_ACTIVITY_CLOSE:
8612                    case AppTransition.TRANSIT_TASK_CLOSE:
8613                    case AppTransition.TRANSIT_TASK_TO_BACK:
8614                        transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE;
8615                        break;
8616                }
8617                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit: " + transit);
8618            } else if ((oldWallpaper != null) && !mOpeningApps.isEmpty()
8619                    && !mOpeningApps.contains(oldWallpaper.mAppToken)) {
8620                // We are transitioning from an activity with
8621                // a wallpaper to one without.
8622                transit = AppTransition.TRANSIT_WALLPAPER_CLOSE;
8623                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8624                        "New transit away from wallpaper: " + transit);
8625            } else if (mWallpaperTarget != null && mWallpaperTarget.isVisibleLw()) {
8626                // We are transitioning from an activity without
8627                // a wallpaper to now showing the wallpaper
8628                transit = AppTransition.TRANSIT_WALLPAPER_OPEN;
8629                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8630                        "New transit into wallpaper: " + transit);
8631            } else {
8632                mAnimateWallpaperWithTarget = true;
8633            }
8634
8635            // If all closing windows are obscured, then there is
8636            // no need to do an animation.  This is the case, for
8637            // example, when this transition is being done behind
8638            // the lock screen.
8639            if (!mPolicy.allowAppAnimationsLw()) {
8640                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8641                        "Animations disallowed by keyguard or dream.");
8642                animLp = null;
8643            }
8644
8645            AppWindowToken topOpeningApp = null;
8646            int topOpeningLayer = 0;
8647
8648            NN = mOpeningApps.size();
8649            for (i=0; i<NN; i++) {
8650                AppWindowToken wtoken = mOpeningApps.get(i);
8651                final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
8652                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken);
8653                appAnimator.clearThumbnail();
8654                wtoken.inPendingTransaction = false;
8655                appAnimator.animation = null;
8656                setTokenVisibilityLocked(wtoken, animLp, true, transit, false);
8657                wtoken.updateReportedVisibilityLocked();
8658                wtoken.waitingToShow = false;
8659
8660                appAnimator.mAllAppWinAnimators.clear();
8661                final int N = wtoken.allAppWindows.size();
8662                for (int j = 0; j < N; j++) {
8663                    appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
8664                }
8665                mAnimator.mAnimating |= appAnimator.showAllWindowsLocked();
8666
8667                if (animLp != null) {
8668                    int layer = -1;
8669                    for (int j=0; j<wtoken.windows.size(); j++) {
8670                        WindowState win = wtoken.windows.get(j);
8671                        if (win.mWinAnimator.mAnimLayer > layer) {
8672                            layer = win.mWinAnimator.mAnimLayer;
8673                        }
8674                    }
8675                    if (topOpeningApp == null || layer > topOpeningLayer) {
8676                        topOpeningApp = wtoken;
8677                        topOpeningLayer = layer;
8678                    }
8679                }
8680            }
8681            NN = mClosingApps.size();
8682            for (i=0; i<NN; i++) {
8683                AppWindowToken wtoken = mClosingApps.get(i);
8684                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken);
8685                wtoken.mAppAnimator.clearThumbnail();
8686                wtoken.inPendingTransaction = false;
8687                wtoken.mAppAnimator.animation = null;
8688                setTokenVisibilityLocked(wtoken, animLp, false, transit, false);
8689                wtoken.updateReportedVisibilityLocked();
8690                wtoken.waitingToHide = false;
8691                // Force the allDrawn flag, because we want to start
8692                // this guy's animations regardless of whether it's
8693                // gotten drawn.
8694                wtoken.allDrawn = true;
8695                wtoken.deferClearAllDrawn = false;
8696            }
8697
8698            boolean useAlternateThumbnailAnimation = true;
8699            AppWindowAnimator appAnimator =
8700                    topOpeningApp == null ? null : topOpeningApp.mAppAnimator;
8701            Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail();
8702            if (!useAlternateThumbnailAnimation && nextAppTransitionThumbnail != null
8703                    && appAnimator != null && appAnimator.animation != null) {
8704                // This thumbnail animation is very special, we need to have
8705                // an extra surface with the thumbnail included with the animation.
8706                Rect dirty = new Rect(0, 0, nextAppTransitionThumbnail.getWidth(),
8707                        nextAppTransitionThumbnail.getHeight());
8708                try {
8709                    // TODO(multi-display): support other displays
8710                    final DisplayContent displayContent = getDefaultDisplayContentLocked();
8711                    final Display display = displayContent.getDisplay();
8712                    SurfaceControl surfaceControl = new SurfaceControl(mFxSession,
8713                            "thumbnail anim",
8714                            dirty.width(), dirty.height(),
8715                            PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
8716                    surfaceControl.setLayerStack(display.getLayerStack());
8717                    appAnimator.thumbnail = surfaceControl;
8718                    if (SHOW_TRANSACTIONS) Slog.i(TAG, "  THUMBNAIL " + surfaceControl + ": CREATE");
8719                    Surface drawSurface = new Surface();
8720                    drawSurface.copyFrom(surfaceControl);
8721                    Canvas c = drawSurface.lockCanvas(dirty);
8722                    c.drawBitmap(nextAppTransitionThumbnail, 0, 0, null);
8723                    drawSurface.unlockCanvasAndPost(c);
8724                    drawSurface.release();
8725                    appAnimator.thumbnailLayer = topOpeningLayer;
8726                    DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
8727                    Animation anim = mAppTransition.createThumbnailScaleAnimationLocked(
8728                            displayInfo.appWidth, displayInfo.appHeight, transit);
8729                    appAnimator.thumbnailAnimation = anim;
8730                    anim.restrictDuration(MAX_ANIMATION_DURATION);
8731                    anim.scaleCurrentDuration(mTransitionAnimationScale);
8732                    Point p = new Point();
8733                    mAppTransition.getStartingPoint(p);
8734                    appAnimator.thumbnailX = p.x;
8735                    appAnimator.thumbnailY = p.y;
8736                } catch (OutOfResourcesException e) {
8737                    Slog.e(TAG, "Can't allocate thumbnail/Canvas surface w=" + dirty.width()
8738                            + " h=" + dirty.height(), e);
8739                    appAnimator.clearThumbnail();
8740                }
8741            }
8742
8743            mAppTransition.postAnimationCallback();
8744            mAppTransition.clear();
8745
8746            mOpeningApps.clear();
8747            mClosingApps.clear();
8748
8749            // This has changed the visibility of windows, so perform
8750            // a new layout to get them all up-to-date.
8751            changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT
8752                    | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
8753            getDefaultDisplayContentLocked().layoutNeeded = true;
8754
8755            // TODO(multidisplay): IMEs are only supported on the default display.
8756            if (windows == getDefaultWindowListLocked()
8757                    && !moveInputMethodWindowsIfNeededLocked(true)) {
8758                assignLayersLocked(windows);
8759            }
8760            updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, false /*updateInputWindows*/);
8761            mFocusMayChange = false;
8762        }
8763
8764        return changes;
8765    }
8766
8767    /**
8768     * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
8769     * @return bitmap indicating if another pass through layout must be made.
8770     */
8771    private int handleAnimatingStoppedAndTransitionLocked() {
8772        int changes = 0;
8773
8774        mAppTransition.setIdle();
8775        // Restore window app tokens to the ActivityManager views
8776        ArrayList<TaskStack> stacks = getDefaultDisplayContentLocked().getStacks();
8777        for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
8778            final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
8779            for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
8780                final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
8781                for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
8782                    tokens.get(tokenNdx).sendingToBottom = false;
8783                }
8784            }
8785        }
8786        rebuildAppWindowListLocked();
8787
8788        changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
8789        if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
8790                "Wallpaper layer changed: assigning layers + relayout");
8791        moveInputMethodWindowsIfNeededLocked(true);
8792        mInnerFields.mWallpaperMayChange = true;
8793        // Since the window list has been rebuilt, focus might
8794        // have to be recomputed since the actual order of windows
8795        // might have changed again.
8796        mFocusMayChange = true;
8797
8798        return changes;
8799    }
8800
8801    private void updateResizingWindows(final WindowState w) {
8802        final WindowStateAnimator winAnimator = w.mWinAnimator;
8803        if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq) {
8804            w.setInsetsChanged();
8805            boolean configChanged = w.isConfigChanged();
8806            if (DEBUG_CONFIGURATION && configChanged) {
8807                Slog.v(TAG, "Win " + w + " config changed: "
8808                        + mCurConfiguration);
8809            }
8810            if (localLOGV) Slog.v(TAG, "Resizing " + w
8811                    + ": configChanged=" + configChanged
8812                    + " last=" + w.mLastFrame + " frame=" + w.mFrame);
8813            w.mLastFrame.set(w.mFrame);
8814            if (w.mContentInsetsChanged
8815                    || w.mVisibleInsetsChanged
8816                    || winAnimator.mSurfaceResized
8817                    || configChanged) {
8818                if (DEBUG_RESIZE || DEBUG_ORIENTATION) {
8819                    Slog.v(TAG, "Resize reasons for w=" + w + ": "
8820                            + " contentInsetsChanged=" + w.mContentInsetsChanged
8821                            + " " + w.mContentInsets.toShortString()
8822                            + " visibleInsetsChanged=" + w.mVisibleInsetsChanged
8823                            + " " + w.mVisibleInsets.toShortString()
8824                            + " surfaceResized=" + winAnimator.mSurfaceResized
8825                            + " configChanged=" + configChanged);
8826                }
8827
8828                w.mLastOverscanInsets.set(w.mOverscanInsets);
8829                w.mLastContentInsets.set(w.mContentInsets);
8830                w.mLastVisibleInsets.set(w.mVisibleInsets);
8831                makeWindowFreezingScreenIfNeededLocked(w);
8832                // If the orientation is changing, then we need to
8833                // hold off on unfreezing the display until this
8834                // window has been redrawn; to do that, we need
8835                // to go through the process of getting informed
8836                // by the application when it has finished drawing.
8837                if (w.mOrientationChanging) {
8838                    if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION) Slog.v(TAG,
8839                            "Orientation start waiting for draw mDrawState=DRAW_PENDING in "
8840                            + w + ", surface " + winAnimator.mSurfaceControl);
8841                    winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
8842                    if (w.mAppToken != null) {
8843                        w.mAppToken.allDrawn = false;
8844                        w.mAppToken.deferClearAllDrawn = false;
8845                    }
8846                }
8847                if (!mResizingWindows.contains(w)) {
8848                    if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
8849                            "Resizing window " + w + " to " + winAnimator.mSurfaceW
8850                            + "x" + winAnimator.mSurfaceH);
8851                    mResizingWindows.add(w);
8852                }
8853            } else if (w.mOrientationChanging) {
8854                if (w.isDrawnLw()) {
8855                    if (DEBUG_ORIENTATION) Slog.v(TAG,
8856                            "Orientation not waiting for draw in "
8857                            + w + ", surface " + winAnimator.mSurfaceControl);
8858                    w.mOrientationChanging = false;
8859                    w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
8860                            - mDisplayFreezeTime);
8861                }
8862            }
8863        }
8864    }
8865
8866    /**
8867     * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
8868     *
8869     * @param w WindowState this method is applied to.
8870     * @param currentTime The time which animations use for calculating transitions.
8871     * @param innerDw Width of app window.
8872     * @param innerDh Height of app window.
8873     */
8874    private void handleNotObscuredLocked(final WindowState w, final long currentTime,
8875                                         final int innerDw, final int innerDh) {
8876        final WindowManager.LayoutParams attrs = w.mAttrs;
8877        final int attrFlags = attrs.flags;
8878        final boolean canBeSeen = w.isDisplayedLw();
8879        final boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn();
8880
8881        if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) {
8882            // This window completely covers everything behind it,
8883            // so we want to leave all of them as undimmed (for
8884            // performance reasons).
8885            mInnerFields.mObscured = true;
8886        }
8887
8888        if (w.mHasSurface) {
8889            if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) {
8890                mInnerFields.mHoldScreen = w.mSession;
8891            }
8892            if (!mInnerFields.mSyswin && w.mAttrs.screenBrightness >= 0
8893                    && mInnerFields.mScreenBrightness < 0) {
8894                mInnerFields.mScreenBrightness = w.mAttrs.screenBrightness;
8895            }
8896            if (!mInnerFields.mSyswin && w.mAttrs.buttonBrightness >= 0
8897                    && mInnerFields.mButtonBrightness < 0) {
8898                mInnerFields.mButtonBrightness = w.mAttrs.buttonBrightness;
8899            }
8900            if (!mInnerFields.mSyswin && w.mAttrs.userActivityTimeout >= 0
8901                    && mInnerFields.mUserActivityTimeout < 0) {
8902                mInnerFields.mUserActivityTimeout = w.mAttrs.userActivityTimeout;
8903            }
8904
8905            final int type = attrs.type;
8906            if (canBeSeen
8907                    && (type == TYPE_SYSTEM_DIALOG
8908                     || type == TYPE_RECENTS_OVERLAY
8909                     || type == TYPE_SYSTEM_ERROR
8910                     || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0)) {
8911                mInnerFields.mSyswin = true;
8912            }
8913
8914            if (canBeSeen) {
8915                // This function assumes that the contents of the default display are
8916                // processed first before secondary displays.
8917                final DisplayContent displayContent = w.getDisplayContent();
8918                if (displayContent != null && displayContent.isDefaultDisplay) {
8919                    // While a dream or keyguard is showing, obscure ordinary application
8920                    // content on secondary displays (by forcibly enabling mirroring unless
8921                    // there is other content we want to show) but still allow opaque
8922                    // keyguard dialogs to be shown.
8923                    if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
8924                        mInnerFields.mObscureApplicationContentOnSecondaryDisplays = true;
8925                    }
8926                    mInnerFields.mDisplayHasContent = true;
8927                } else if (displayContent != null &&
8928                        (!mInnerFields.mObscureApplicationContentOnSecondaryDisplays
8929                        || (mInnerFields.mObscured && type == TYPE_KEYGUARD_DIALOG))) {
8930                    // Allow full screen keyguard presentation dialogs to be seen.
8931                    mInnerFields.mDisplayHasContent = true;
8932                }
8933            }
8934        }
8935    }
8936
8937    private void handleFlagDimBehind(WindowState w) {
8938        final WindowManager.LayoutParams attrs = w.mAttrs;
8939        if ((attrs.flags & FLAG_DIM_BEHIND) != 0
8940                && w.isDisplayedLw()
8941                && !w.mExiting) {
8942            final WindowStateAnimator winAnimator = w.mWinAnimator;
8943            final TaskStack stack = w.getStack();
8944            stack.setDimmingTag();
8945            if (!stack.isDimming(winAnimator)) {
8946                if (localLOGV) Slog.v(TAG, "Win " + w + " start dimming.");
8947                stack.startDimmingIfNeeded(winAnimator);
8948            }
8949        }
8950    }
8951
8952    private void updateAllDrawnLocked(DisplayContent displayContent) {
8953        // See if any windows have been drawn, so they (and others
8954        // associated with them) can now be shown.
8955        ArrayList<TaskStack> stacks = displayContent.getStacks();
8956        for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
8957            final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
8958            for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
8959                final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
8960                for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
8961                    final AppWindowToken wtoken = tokens.get(tokenNdx);
8962                    if (!wtoken.allDrawn) {
8963                        int numInteresting = wtoken.numInterestingWindows;
8964                        if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
8965                            if (DEBUG_VISIBILITY) Slog.v(TAG,
8966                                    "allDrawn: " + wtoken
8967                                    + " interesting=" + numInteresting
8968                                    + " drawn=" + wtoken.numDrawnWindows);
8969                            wtoken.allDrawn = true;
8970                            mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, wtoken.token).sendToTarget();
8971                        }
8972                    }
8973                }
8974            }
8975        }
8976    }
8977
8978    // "Something has changed!  Let's make it correct now."
8979    private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) {
8980        if (DEBUG_WINDOW_TRACE) {
8981            Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by "
8982                    + Debug.getCallers(3));
8983        }
8984
8985        final long currentTime = SystemClock.uptimeMillis();
8986
8987        int i;
8988
8989        if (mFocusMayChange) {
8990            mFocusMayChange = false;
8991            updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
8992                    false /*updateInputWindows*/);
8993        }
8994
8995        // Initialize state of exiting tokens.
8996        final int numDisplays = mDisplayContents.size();
8997        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
8998            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
8999            for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) {
9000                displayContent.mExitingTokens.get(i).hasVisible = false;
9001            }
9002        }
9003
9004        for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
9005            // Initialize state of exiting applications.
9006            final AppTokenList exitingAppTokens =
9007                    mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
9008            for (int tokenNdx = exitingAppTokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
9009                exitingAppTokens.get(tokenNdx).hasVisible = false;
9010            }
9011        }
9012
9013        mInnerFields.mHoldScreen = null;
9014        mInnerFields.mScreenBrightness = -1;
9015        mInnerFields.mButtonBrightness = -1;
9016        mInnerFields.mUserActivityTimeout = -1;
9017        mInnerFields.mObscureApplicationContentOnSecondaryDisplays = false;
9018
9019        mTransactionSequence++;
9020
9021        final DisplayContent defaultDisplay = getDefaultDisplayContentLocked();
9022        final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo();
9023        final int defaultDw = defaultInfo.logicalWidth;
9024        final int defaultDh = defaultInfo.logicalHeight;
9025
9026        if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
9027                ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
9028        SurfaceControl.openTransaction();
9029        try {
9030
9031            if (mWatermark != null) {
9032                mWatermark.positionSurface(defaultDw, defaultDh);
9033            }
9034            if (mStrictModeFlash != null) {
9035                mStrictModeFlash.positionSurface(defaultDw, defaultDh);
9036            }
9037            if (mCircularDisplayMask != null) {
9038                mCircularDisplayMask.positionSurface(defaultDw, defaultDh, mRotation);
9039            }
9040
9041            boolean focusDisplayed = false;
9042
9043            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9044                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9045                boolean updateAllDrawn = false;
9046                WindowList windows = displayContent.getWindowList();
9047                DisplayInfo displayInfo = displayContent.getDisplayInfo();
9048                final int displayId = displayContent.getDisplayId();
9049                final int dw = displayInfo.logicalWidth;
9050                final int dh = displayInfo.logicalHeight;
9051                final int innerDw = displayInfo.appWidth;
9052                final int innerDh = displayInfo.appHeight;
9053                final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
9054
9055                // Reset for each display.
9056                mInnerFields.mDisplayHasContent = false;
9057
9058                int repeats = 0;
9059                do {
9060                    repeats++;
9061                    if (repeats > 6) {
9062                        Slog.w(TAG, "Animation repeat aborted after too many iterations");
9063                        displayContent.layoutNeeded = false;
9064                        break;
9065                    }
9066
9067                    if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner",
9068                        displayContent.pendingLayoutChanges);
9069
9070                    if ((displayContent.pendingLayoutChanges &
9071                            WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0 &&
9072                            (adjustWallpaperWindowsLocked() &
9073                                    ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
9074                        assignLayersLocked(windows);
9075                        displayContent.layoutNeeded = true;
9076                    }
9077
9078                    if (isDefaultDisplay && (displayContent.pendingLayoutChanges
9079                            & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
9080                        if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
9081                        if (updateOrientationFromAppTokensLocked(true)) {
9082                            displayContent.layoutNeeded = true;
9083                            mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
9084                        }
9085                    }
9086
9087                    if ((displayContent.pendingLayoutChanges
9088                            & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
9089                        displayContent.layoutNeeded = true;
9090                    }
9091
9092                    // FIRST LOOP: Perform a layout, if needed.
9093                    if (repeats < 4) {
9094                        performLayoutLockedInner(displayContent, repeats == 1,
9095                                false /*updateInputWindows*/);
9096                    } else {
9097                        Slog.w(TAG, "Layout repeat skipped after too many iterations");
9098                    }
9099
9100                    // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think
9101                    // it is animating.
9102                    displayContent.pendingLayoutChanges = 0;
9103
9104                    if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number "
9105                            + mLayoutRepeatCount, displayContent.pendingLayoutChanges);
9106
9107                    if (isDefaultDisplay) {
9108                        mPolicy.beginPostLayoutPolicyLw(dw, dh);
9109                        for (i = windows.size() - 1; i >= 0; i--) {
9110                            WindowState w = windows.get(i);
9111                            if (w.mHasSurface) {
9112                                mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs);
9113                            }
9114                        }
9115                        displayContent.pendingLayoutChanges |= mPolicy.finishPostLayoutPolicyLw();
9116                        if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats(
9117                            "after finishPostLayoutPolicyLw", displayContent.pendingLayoutChanges);
9118                    }
9119                } while (displayContent.pendingLayoutChanges != 0);
9120
9121                mInnerFields.mObscured = false;
9122                mInnerFields.mSyswin = false;
9123                displayContent.resetDimming();
9124
9125                // Only used if default window
9126                final boolean someoneLosingFocus = !mLosingFocus.isEmpty();
9127
9128                final int N = windows.size();
9129                for (i=N-1; i>=0; i--) {
9130                    WindowState w = windows.get(i);
9131                    final TaskStack stack = w.getStack();
9132                    if (stack == null) {
9133                        continue;
9134                    }
9135
9136                    final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured;
9137
9138                    // Update effect.
9139                    w.mObscured = mInnerFields.mObscured;
9140                    if (!mInnerFields.mObscured) {
9141                        handleNotObscuredLocked(w, currentTime, innerDw, innerDh);
9142                    }
9143
9144                    if (!stack.testDimmingTag()) {
9145                        handleFlagDimBehind(w);
9146                    }
9147
9148                    if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w)
9149                            && w.isVisibleLw()) {
9150                        // This is the wallpaper target and its obscured state
9151                        // changed... make sure the current wallaper's visibility
9152                        // has been updated accordingly.
9153                        updateWallpaperVisibilityLocked();
9154                    }
9155
9156                    final WindowStateAnimator winAnimator = w.mWinAnimator;
9157
9158                    // If the window has moved due to its containing
9159                    // content frame changing, then we'd like to animate
9160                    // it.
9161                    if (w.mHasSurface && w.shouldAnimateMove()) {
9162                        // Frame has moved, containing content frame
9163                        // has also moved, and we're not currently animating...
9164                        // let's do something.
9165                        Animation a = AnimationUtils.loadAnimation(mContext,
9166                                com.android.internal.R.anim.window_move_from_decor);
9167                        winAnimator.setAnimation(a);
9168                        winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left;
9169                        winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top;
9170                        try {
9171                            w.mClient.moved(w.mFrame.left, w.mFrame.top);
9172                        } catch (RemoteException e) {
9173                        }
9174                    }
9175
9176                    //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
9177                    w.mContentChanged = false;
9178
9179                    // Moved from updateWindowsAndWallpaperLocked().
9180                    if (w.mHasSurface) {
9181                        // Take care of the window being ready to display.
9182                        final boolean committed =
9183                                winAnimator.commitFinishDrawingLocked(currentTime);
9184                        if (isDefaultDisplay && committed) {
9185                            if (w.mAttrs.type == TYPE_DREAM) {
9186                                // HACK: When a dream is shown, it may at that
9187                                // point hide the lock screen.  So we need to
9188                                // redo the layout to let the phone window manager
9189                                // make this happen.
9190                                displayContent.pendingLayoutChanges |=
9191                                        WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9192                                if (DEBUG_LAYOUT_REPEATS) {
9193                                    debugLayoutRepeats(
9194                                        "dream and commitFinishDrawingLocked true",
9195                                        displayContent.pendingLayoutChanges);
9196                                }
9197                            }
9198                            if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
9199                                if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
9200                                        "First draw done in potential wallpaper target " + w);
9201                                mInnerFields.mWallpaperMayChange = true;
9202                                displayContent.pendingLayoutChanges |=
9203                                        WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
9204                                if (DEBUG_LAYOUT_REPEATS) {
9205                                    debugLayoutRepeats(
9206                                        "wallpaper and commitFinishDrawingLocked true",
9207                                        displayContent.pendingLayoutChanges);
9208                                }
9209                            }
9210                        }
9211
9212                        winAnimator.setSurfaceBoundariesLocked(recoveringMemory);
9213
9214                        final AppWindowToken atoken = w.mAppToken;
9215                        if (DEBUG_STARTING_WINDOW && atoken != null
9216                                && w == atoken.startingWindow) {
9217                            Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen="
9218                                + w.isOnScreen() + " allDrawn=" + atoken.allDrawn
9219                                + " freezingScreen=" + atoken.mAppAnimator.freezingScreen);
9220                        }
9221                        if (atoken != null
9222                                && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) {
9223                            if (atoken.lastTransactionSequence != mTransactionSequence) {
9224                                atoken.lastTransactionSequence = mTransactionSequence;
9225                                atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
9226                                atoken.startingDisplayed = false;
9227                            }
9228                            if ((w.isOnScreen() || winAnimator.mAttrType == TYPE_BASE_APPLICATION)
9229                                    && !w.mExiting && !w.mDestroying) {
9230                                if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
9231                                    Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
9232                                            + ", isAnimating=" + winAnimator.isAnimating());
9233                                    if (!w.isDrawnLw()) {
9234                                        Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceControl
9235                                                + " pv=" + w.mPolicyVisibility
9236                                                + " mDrawState=" + winAnimator.mDrawState
9237                                                + " ah=" + w.mAttachedHidden
9238                                                + " th=" + atoken.hiddenRequested
9239                                                + " a=" + winAnimator.mAnimating);
9240                                    }
9241                                }
9242                                if (w != atoken.startingWindow) {
9243                                    if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) {
9244                                        atoken.numInterestingWindows++;
9245                                        if (w.isDrawnLw()) {
9246                                            atoken.numDrawnWindows++;
9247                                            if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG,
9248                                                    "tokenMayBeDrawn: " + atoken
9249                                                    + " freezingScreen=" + atoken.mAppAnimator.freezingScreen
9250                                                    + " mAppFreezing=" + w.mAppFreezing);
9251                                            updateAllDrawn = true;
9252                                        }
9253                                    }
9254                                } else if (w.isDrawnLw()) {
9255                                    atoken.startingDisplayed = true;
9256                                }
9257                            }
9258                        }
9259                    }
9260
9261                    if (isDefaultDisplay && someoneLosingFocus && (w == mCurrentFocus)
9262                            && w.isDisplayedLw()) {
9263                        focusDisplayed = true;
9264                    }
9265
9266                    updateResizingWindows(w);
9267                }
9268
9269                mDisplayManagerInternal.setDisplayHasContent(displayId,
9270                        mInnerFields.mDisplayHasContent,
9271                        true /* inTraversal, must call performTraversalInTrans... below */);
9272
9273                getDisplayContentLocked(displayId).stopDimmingIfNeeded();
9274
9275                if (updateAllDrawn) {
9276                    updateAllDrawnLocked(displayContent);
9277                }
9278            }
9279
9280            if (focusDisplayed) {
9281                mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS);
9282            }
9283
9284            // Give the display manager a chance to adjust properties
9285            // like display rotation if it needs to.
9286            mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
9287
9288        } catch (RuntimeException e) {
9289            Log.wtf(TAG, "Unhandled exception in Window Manager", e);
9290        } finally {
9291            SurfaceControl.closeTransaction();
9292            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
9293                    "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
9294        }
9295
9296        final WindowList defaultWindows = defaultDisplay.getWindowList();
9297
9298        // If we are ready to perform an app transition, check through
9299        // all of the app tokens to be shown and see if they are ready
9300        // to go.
9301        if (mAppTransition.isReady()) {
9302            defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows);
9303            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked",
9304                    defaultDisplay.pendingLayoutChanges);
9305        }
9306
9307        if (!mAnimator.mAnimating && mAppTransition.isRunning()) {
9308            // We have finished the animation of an app transition.  To do
9309            // this, we have delayed a lot of operations like showing and
9310            // hiding apps, moving apps in Z-order, etc.  The app token list
9311            // reflects the correct Z-order, but the window list may now
9312            // be out of sync with it.  So here we will just rebuild the
9313            // entire app window list.  Fun!
9314            defaultDisplay.pendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked();
9315            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock",
9316                defaultDisplay.pendingLayoutChanges);
9317        }
9318
9319        if (mInnerFields.mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0
9320                && !mAppTransition.isReady()) {
9321            // At this point, there was a window with a wallpaper that
9322            // was force hiding other windows behind it, but now it
9323            // is going away.  This may be simple -- just animate
9324            // away the wallpaper and its window -- or it may be
9325            // hard -- the wallpaper now needs to be shown behind
9326            // something that was hidden.
9327            defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9328            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked",
9329                defaultDisplay.pendingLayoutChanges);
9330        }
9331        mInnerFields.mWallpaperForceHidingChanged = false;
9332
9333        if (mInnerFields.mWallpaperMayChange) {
9334            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Wallpaper may change!  Adjusting");
9335            defaultDisplay.pendingLayoutChanges |=
9336                    WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
9337            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("WallpaperMayChange",
9338                    defaultDisplay.pendingLayoutChanges);
9339        }
9340
9341        if (mFocusMayChange) {
9342            mFocusMayChange = false;
9343            if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
9344                    false /*updateInputWindows*/)) {
9345                defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
9346            }
9347        }
9348
9349        if (needsLayout()) {
9350            defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9351            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded",
9352                    defaultDisplay.pendingLayoutChanges);
9353        }
9354
9355        for (i = mResizingWindows.size() - 1; i >= 0; i--) {
9356            WindowState win = mResizingWindows.get(i);
9357            if (win.mAppFreezing) {
9358                // Don't remove this window until rotation has completed.
9359                continue;
9360            }
9361            win.reportResized();
9362            mResizingWindows.remove(i);
9363        }
9364
9365        if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG,
9366                "With display frozen, orientationChangeComplete="
9367                + mInnerFields.mOrientationChangeComplete);
9368        if (mInnerFields.mOrientationChangeComplete) {
9369            if (mWindowsFreezingScreen) {
9370                mWindowsFreezingScreen = false;
9371                mLastFinishedFreezeSource = mInnerFields.mLastWindowFreezeSource;
9372                mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
9373            }
9374            stopFreezingDisplayLocked();
9375        }
9376
9377        // Destroy the surface of any windows that are no longer visible.
9378        boolean wallpaperDestroyed = false;
9379        i = mDestroySurface.size();
9380        if (i > 0) {
9381            do {
9382                i--;
9383                WindowState win = mDestroySurface.get(i);
9384                win.mDestroying = false;
9385                if (mInputMethodWindow == win) {
9386                    mInputMethodWindow = null;
9387                }
9388                if (win == mWallpaperTarget) {
9389                    wallpaperDestroyed = true;
9390                }
9391                win.mWinAnimator.destroySurfaceLocked();
9392            } while (i > 0);
9393            mDestroySurface.clear();
9394        }
9395
9396        // Time to remove any exiting tokens?
9397        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9398            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9399            ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens;
9400            for (i = exitingTokens.size() - 1; i >= 0; i--) {
9401                WindowToken token = exitingTokens.get(i);
9402                if (!token.hasVisible) {
9403                    exitingTokens.remove(i);
9404                    if (token.windowType == TYPE_WALLPAPER) {
9405                        mWallpaperTokens.remove(token);
9406                    }
9407                }
9408            }
9409        }
9410
9411        // Time to remove any exiting applications?
9412        for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
9413            // Initialize state of exiting applications.
9414            final AppTokenList exitingAppTokens =
9415                    mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
9416            for (i = exitingAppTokens.size() - 1; i >= 0; i--) {
9417                AppWindowToken token = exitingAppTokens.get(i);
9418                if (!token.hasVisible && !mClosingApps.contains(token) && !token.mDeferRemoval) {
9419                    // Make sure there is no animation running on this token,
9420                    // so any windows associated with it will be removed as
9421                    // soon as their animations are complete
9422                    token.mAppAnimator.clearAnimation();
9423                    token.mAppAnimator.animating = false;
9424                    if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
9425                            "performLayout: App token exiting now removed" + token);
9426                    removeAppFromTaskLocked(token);
9427                    exitingAppTokens.remove(i);
9428                }
9429            }
9430        }
9431
9432        if (!mAnimator.mAnimating && mRelayoutWhileAnimating.size() > 0) {
9433            for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) {
9434                try {
9435                    mRelayoutWhileAnimating.get(j).mClient.doneAnimating();
9436                } catch (RemoteException e) {
9437                }
9438            }
9439            mRelayoutWhileAnimating.clear();
9440        }
9441
9442        if (wallpaperDestroyed) {
9443            defaultDisplay.pendingLayoutChanges |=
9444                    WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
9445            defaultDisplay.layoutNeeded = true;
9446        }
9447
9448        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9449            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9450            if (displayContent.pendingLayoutChanges != 0) {
9451                displayContent.layoutNeeded = true;
9452            }
9453        }
9454
9455        // Finally update all input windows now that the window changes have stabilized.
9456        mInputMonitor.updateInputWindowsLw(true /*force*/);
9457
9458        setHoldScreenLocked(mInnerFields.mHoldScreen);
9459        if (!mDisplayFrozen) {
9460            if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) {
9461                mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(-1);
9462            } else {
9463                mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(
9464                        toBrightnessOverride(mInnerFields.mScreenBrightness));
9465            }
9466            if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) {
9467                mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(-1);
9468            } else {
9469                mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(
9470                        toBrightnessOverride(mInnerFields.mButtonBrightness));
9471            }
9472            mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager(
9473                    mInnerFields.mUserActivityTimeout);
9474        }
9475
9476        if (mTurnOnScreen) {
9477            if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!");
9478            mPowerManager.wakeUp(SystemClock.uptimeMillis());
9479            mTurnOnScreen = false;
9480        }
9481
9482        if (mInnerFields.mUpdateRotation) {
9483            if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
9484            if (updateRotationUncheckedLocked(false)) {
9485                mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
9486            } else {
9487                mInnerFields.mUpdateRotation = false;
9488            }
9489        }
9490
9491        if (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded
9492                && !mInnerFields.mUpdateRotation) {
9493            checkDrawnWindowsLocked();
9494        }
9495
9496        final int N = mPendingRemove.size();
9497        if (N > 0) {
9498            if (mPendingRemoveTmp.length < N) {
9499                mPendingRemoveTmp = new WindowState[N+10];
9500            }
9501            mPendingRemove.toArray(mPendingRemoveTmp);
9502            mPendingRemove.clear();
9503            DisplayContentList displayList = new DisplayContentList();
9504            for (i = 0; i < N; i++) {
9505                WindowState w = mPendingRemoveTmp[i];
9506                removeWindowInnerLocked(w.mSession, w);
9507                final DisplayContent displayContent = w.getDisplayContent();
9508                if (displayContent != null && !displayList.contains(displayContent)) {
9509                    displayList.add(displayContent);
9510                }
9511            }
9512
9513            for (DisplayContent displayContent : displayList) {
9514                assignLayersLocked(displayContent.getWindowList());
9515                displayContent.layoutNeeded = true;
9516            }
9517        }
9518
9519        // Remove all deferred displays stacks, tasks, and activities.
9520        for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
9521            mDisplayContents.valueAt(displayNdx).checkForDeferredActions();
9522        }
9523
9524        setFocusedStackFrame();
9525
9526        // Check to see if we are now in a state where the screen should
9527        // be enabled, because the window obscured flags have changed.
9528        enableScreenIfNeededLocked();
9529
9530        scheduleAnimationLocked();
9531
9532        if (DEBUG_WINDOW_TRACE) {
9533            Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: animating="
9534                    + mAnimator.mAnimating);
9535        }
9536    }
9537
9538    private int toBrightnessOverride(float value) {
9539        return (int)(value * PowerManager.BRIGHTNESS_ON);
9540    }
9541
9542    void checkDrawnWindowsLocked() {
9543        if (mWaitingForDrawn.size() > 0) {
9544            for (int j=mWaitingForDrawn.size()-1; j>=0; j--) {
9545                Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(j);
9546                WindowState win = pair.first;
9547                //Slog.i(TAG, "Waiting for drawn " + win + ": removed="
9548                //        + win.mRemoved + " visible=" + win.isVisibleLw()
9549                //        + " shown=" + win.mSurfaceShown);
9550                if (win.mRemoved) {
9551                    // Window has been removed; no draw will now happen, so stop waiting.
9552                    Slog.w(TAG, "Aborted waiting for drawn: " + pair.first);
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                } else if (win.mWinAnimator.mSurfaceShown) {
9560                    // Window is now drawn (and shown).
9561                    try {
9562                        pair.second.sendResult(null);
9563                    } catch (RemoteException e) {
9564                    }
9565                    mWaitingForDrawn.remove(pair);
9566                    mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
9567                }
9568            }
9569        }
9570    }
9571
9572    @Override
9573    public boolean waitForWindowDrawn(IBinder token, IRemoteCallback callback) {
9574        if (token != null && callback != null) {
9575            synchronized (mWindowMap) {
9576                WindowState win = windowForClientLocked(null, token, true);
9577                if (win != null) {
9578                    Pair<WindowState, IRemoteCallback> pair =
9579                            new Pair<WindowState, IRemoteCallback>(win, callback);
9580                    Message m = mH.obtainMessage(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
9581                    mH.sendMessageDelayed(m, 2000);
9582                    mWaitingForDrawn.add(pair);
9583                    checkDrawnWindowsLocked();
9584                    return true;
9585                }
9586                Slog.i(TAG, "waitForWindowDrawn: win null");
9587            }
9588        }
9589        return false;
9590    }
9591
9592    void setHoldScreenLocked(final Session newHoldScreen) {
9593        final boolean hold = newHoldScreen != null;
9594
9595        if (hold && mHoldingScreenOn != newHoldScreen) {
9596            mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid));
9597        }
9598        mHoldingScreenOn = newHoldScreen;
9599
9600        final boolean state = mHoldingScreenWakeLock.isHeld();
9601        if (hold != state) {
9602            if (hold) {
9603                mHoldingScreenWakeLock.acquire();
9604                mPolicy.keepScreenOnStartedLw();
9605            } else {
9606                mPolicy.keepScreenOnStoppedLw();
9607                mHoldingScreenWakeLock.release();
9608            }
9609        }
9610    }
9611
9612    void requestTraversal() {
9613        synchronized (mWindowMap) {
9614            requestTraversalLocked();
9615        }
9616    }
9617
9618    void requestTraversalLocked() {
9619        if (!mTraversalScheduled) {
9620            mTraversalScheduled = true;
9621            mH.sendEmptyMessage(H.DO_TRAVERSAL);
9622        }
9623    }
9624
9625    /** Note that Locked in this case is on mLayoutToAnim */
9626    void scheduleAnimationLocked() {
9627        if (!mAnimationScheduled) {
9628            mAnimationScheduled = true;
9629            mChoreographer.postCallback(
9630                    Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null);
9631        }
9632    }
9633
9634    private boolean needsLayout() {
9635        final int numDisplays = mDisplayContents.size();
9636        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9637            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9638            if (displayContent.layoutNeeded) {
9639                return true;
9640            }
9641        }
9642        return false;
9643    }
9644
9645    boolean copyAnimToLayoutParamsLocked() {
9646        boolean doRequest = false;
9647
9648        final int bulkUpdateParams = mAnimator.mBulkUpdateParams;
9649        if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) {
9650            mInnerFields.mUpdateRotation = true;
9651            doRequest = true;
9652        }
9653        if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) {
9654            mInnerFields.mWallpaperMayChange = true;
9655            doRequest = true;
9656        }
9657        if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) {
9658            mInnerFields.mWallpaperForceHidingChanged = true;
9659            doRequest = true;
9660        }
9661        if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) == 0) {
9662            mInnerFields.mOrientationChangeComplete = false;
9663        } else {
9664            mInnerFields.mOrientationChangeComplete = true;
9665            mInnerFields.mLastWindowFreezeSource = mAnimator.mLastWindowFreezeSource;
9666            if (mWindowsFreezingScreen) {
9667                doRequest = true;
9668            }
9669        }
9670        if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) {
9671            mTurnOnScreen = true;
9672        }
9673        if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_ACTION_PENDING) != 0) {
9674            mInnerFields.mWallpaperActionPending = true;
9675        }
9676
9677        return doRequest;
9678    }
9679
9680    /** If a window that has an animation specifying a colored background and the current wallpaper
9681     * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to
9682     * suddenly disappear. */
9683    int adjustAnimationBackground(WindowStateAnimator winAnimator) {
9684        WindowList windows = winAnimator.mWin.getWindowList();
9685        for (int i = windows.size() - 1; i >= 0; --i) {
9686            WindowState testWin = windows.get(i);
9687            if (testWin.mIsWallpaper && testWin.isVisibleNow()) {
9688                return testWin.mWinAnimator.mAnimLayer;
9689            }
9690        }
9691        return winAnimator.mAnimLayer;
9692    }
9693
9694    boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation,
9695                                           boolean secure) {
9696        final SurfaceControl surface = winAnimator.mSurfaceControl;
9697        boolean leakedSurface = false;
9698        boolean killedApps = false;
9699
9700        EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(),
9701                winAnimator.mSession.mPid, operation);
9702
9703        if (mForceRemoves == null) {
9704            mForceRemoves = new ArrayList<WindowState>();
9705        }
9706
9707        long callingIdentity = Binder.clearCallingIdentity();
9708        try {
9709            // There was some problem...   first, do a sanity check of the
9710            // window list to make sure we haven't left any dangling surfaces
9711            // around.
9712
9713            Slog.i(TAG, "Out of memory for surface!  Looking for leaks...");
9714            final int numDisplays = mDisplayContents.size();
9715            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9716                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
9717                final int numWindows = windows.size();
9718                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
9719                    final WindowState ws = windows.get(winNdx);
9720                    WindowStateAnimator wsa = ws.mWinAnimator;
9721                    if (wsa.mSurfaceControl != null) {
9722                        if (!mSessions.contains(wsa.mSession)) {
9723                            Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): "
9724                                    + ws + " surface=" + wsa.mSurfaceControl
9725                                    + " token=" + ws.mToken
9726                                    + " pid=" + ws.mSession.mPid
9727                                    + " uid=" + ws.mSession.mUid);
9728                            if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null);
9729                            wsa.mSurfaceControl.destroy();
9730                            wsa.mSurfaceShown = false;
9731                            wsa.mSurfaceControl = null;
9732                            ws.mHasSurface = false;
9733                            mForceRemoves.add(ws);
9734                            leakedSurface = true;
9735                        } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) {
9736                            Slog.w(TAG, "LEAKED SURFACE (app token hidden): "
9737                                    + ws + " surface=" + wsa.mSurfaceControl
9738                                    + " token=" + ws.mAppToken);
9739                            if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null);
9740                            wsa.mSurfaceControl.destroy();
9741                            wsa.mSurfaceShown = false;
9742                            wsa.mSurfaceControl = null;
9743                            ws.mHasSurface = false;
9744                            leakedSurface = true;
9745                        }
9746                    }
9747                }
9748            }
9749
9750            if (!leakedSurface) {
9751                Slog.w(TAG, "No leaked surfaces; killing applicatons!");
9752                SparseIntArray pidCandidates = new SparseIntArray();
9753                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9754                    final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
9755                    final int numWindows = windows.size();
9756                    for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
9757                        final WindowState ws = windows.get(winNdx);
9758                        if (mForceRemoves.contains(ws)) {
9759                            continue;
9760                        }
9761                        WindowStateAnimator wsa = ws.mWinAnimator;
9762                        if (wsa.mSurfaceControl != null) {
9763                            pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid);
9764                        }
9765                    }
9766                    if (pidCandidates.size() > 0) {
9767                        int[] pids = new int[pidCandidates.size()];
9768                        for (int i=0; i<pids.length; i++) {
9769                            pids[i] = pidCandidates.keyAt(i);
9770                        }
9771                        try {
9772                            if (mActivityManager.killPids(pids, "Free memory", secure)) {
9773                                killedApps = true;
9774                            }
9775                        } catch (RemoteException e) {
9776                        }
9777                    }
9778                }
9779            }
9780
9781            if (leakedSurface || killedApps) {
9782                // We managed to reclaim some memory, so get rid of the trouble
9783                // surface and ask the app to request another one.
9784                Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry.");
9785                if (surface != null) {
9786                    if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin,
9787                            "RECOVER DESTROY", null);
9788                    surface.destroy();
9789                    winAnimator.mSurfaceShown = false;
9790                    winAnimator.mSurfaceControl = null;
9791                    winAnimator.mWin.mHasSurface = false;
9792                    scheduleRemoveStartingWindow(winAnimator.mWin.mAppToken);
9793                }
9794
9795                try {
9796                    winAnimator.mWin.mClient.dispatchGetNewSurface();
9797                } catch (RemoteException e) {
9798                }
9799            }
9800        } finally {
9801            Binder.restoreCallingIdentity(callingIdentity);
9802        }
9803
9804        return leakedSurface || killedApps;
9805    }
9806
9807    private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
9808        WindowState newFocus = computeFocusedWindowLocked();
9809        if (mCurrentFocus != newFocus) {
9810            Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus");
9811            // This check makes sure that we don't already have the focus
9812            // change message pending.
9813            mH.removeMessages(H.REPORT_FOCUS_CHANGE);
9814            mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
9815            // TODO(multidisplay): Focused windows on default display only.
9816            final DisplayContent displayContent = getDefaultDisplayContentLocked();
9817            final boolean imWindowChanged = moveInputMethodWindowsIfNeededLocked(
9818                    mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS
9819                            && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES);
9820            if (imWindowChanged) {
9821                displayContent.layoutNeeded = true;
9822                newFocus = computeFocusedWindowLocked();
9823            }
9824
9825            if (DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG, "Changing focus from " +
9826                    mCurrentFocus + " to " + newFocus + " Callers=" + Debug.getCallers(4));
9827            final WindowState oldFocus = mCurrentFocus;
9828            mCurrentFocus = newFocus;
9829            mLosingFocus.remove(newFocus);
9830
9831            if (mAccessibilityController != null) {
9832                mAccessibilityController.onWindowFocusChangedLocked();
9833            }
9834
9835            int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
9836
9837            if (imWindowChanged && oldFocus != mInputMethodWindow) {
9838                // Focus of the input method window changed. Perform layout if needed.
9839                if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
9840                    performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows);
9841                    focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9842                } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
9843                    // Client will do the layout, but we need to assign layers
9844                    // for handleNewWindowLocked() below.
9845                    assignLayersLocked(displayContent.getWindowList());
9846                }
9847            }
9848
9849            if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
9850                // The change in focus caused us to need to do a layout.  Okay.
9851                displayContent.layoutNeeded = true;
9852                if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
9853                    performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows);
9854                }
9855            }
9856
9857            if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
9858                // If we defer assigning layers, then the caller is responsible for
9859                // doing this part.
9860                finishUpdateFocusedWindowAfterAssignLayersLocked(updateInputWindows);
9861            }
9862
9863            Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
9864            return true;
9865        }
9866        return false;
9867    }
9868
9869    private void finishUpdateFocusedWindowAfterAssignLayersLocked(boolean updateInputWindows) {
9870        mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows);
9871    }
9872
9873    private WindowState computeFocusedWindowLocked() {
9874        if (mAnimator.mUniverseBackground != null
9875                && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) {
9876            return mAnimator.mUniverseBackground.mWin;
9877        }
9878
9879        final int displayCount = mDisplayContents.size();
9880        for (int i = 0; i < displayCount; i++) {
9881            final DisplayContent displayContent = mDisplayContents.valueAt(i);
9882            WindowState win = findFocusedWindowLocked(displayContent);
9883            if (win != null) {
9884                return win;
9885            }
9886        }
9887        return null;
9888    }
9889
9890    private WindowState findFocusedWindowLocked(DisplayContent displayContent) {
9891        final WindowList windows = displayContent.getWindowList();
9892        for (int i = windows.size() - 1; i >= 0; i--) {
9893            final WindowState win = windows.get(i);
9894
9895            if (localLOGV || DEBUG_FOCUS) Slog.v(
9896                TAG, "Looking for focus: " + i
9897                + " = " + win
9898                + ", flags=" + win.mAttrs.flags
9899                + ", canReceive=" + win.canReceiveKeys());
9900
9901            AppWindowToken wtoken = win.mAppToken;
9902
9903            // If this window's application has been removed, just skip it.
9904            if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) {
9905                if (DEBUG_FOCUS) Slog.v(TAG, "Skipping " + wtoken + " because "
9906                        + (wtoken.removed ? "removed" : "sendingToBottom"));
9907                continue;
9908            }
9909
9910            if (!win.canReceiveKeys()) {
9911                continue;
9912            }
9913
9914            // Descend through all of the app tokens and find the first that either matches
9915            // win.mAppToken (return win) or mFocusedApp (return null).
9916            if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING &&
9917                    mFocusedApp != null) {
9918                ArrayList<Task> tasks = displayContent.getTasks();
9919                for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
9920                    AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
9921                    int tokenNdx = tokens.size() - 1;
9922                    for ( ; tokenNdx >= 0; --tokenNdx) {
9923                        final AppWindowToken token = tokens.get(tokenNdx);
9924                        if (wtoken == token) {
9925                            break;
9926                        }
9927                        if (mFocusedApp == token) {
9928                            // Whoops, we are below the focused app...  no focus for you!
9929                            if (localLOGV || DEBUG_FOCUS_LIGHT) Slog.v(TAG,
9930                                    "findFocusedWindow: Reached focused app=" + mFocusedApp);
9931                            return null;
9932                        }
9933                    }
9934                    if (tokenNdx >= 0) {
9935                        // Early exit from loop, must have found the matching token.
9936                        break;
9937                    }
9938                }
9939            }
9940
9941            if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: Found new focus @ " + i +
9942                        " = " + win);
9943            return win;
9944        }
9945
9946        if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: No focusable windows.");
9947        return null;
9948    }
9949
9950    private void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) {
9951        if (mDisplayFrozen) {
9952            return;
9953        }
9954
9955        if (!mDisplayReady || !mPolicy.isScreenOnFully()) {
9956            // No need to freeze the screen before the system is ready or if
9957            // the screen is off.
9958            return;
9959        }
9960
9961        mScreenFrozenLock.acquire();
9962
9963        mDisplayFrozen = true;
9964        mDisplayFreezeTime = SystemClock.elapsedRealtime();
9965        mLastFinishedFreezeSource = null;
9966
9967        mInputMonitor.freezeInputDispatchingLw();
9968
9969        // Clear the last input window -- that is just used for
9970        // clean transitions between IMEs, and if we are freezing
9971        // the screen then the whole world is changing behind the scenes.
9972        mPolicy.setLastInputMethodWindowLw(null, null);
9973
9974        if (mAppTransition.isTransitionSet()) {
9975            mAppTransition.freeze();
9976        }
9977
9978        if (PROFILE_ORIENTATION) {
9979            File file = new File("/data/system/frozen");
9980            Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
9981        }
9982
9983        if (CUSTOM_SCREEN_ROTATION) {
9984            mExitAnimId = exitAnim;
9985            mEnterAnimId = enterAnim;
9986            final DisplayContent displayContent = getDefaultDisplayContentLocked();
9987            final int displayId = displayContent.getDisplayId();
9988            ScreenRotationAnimation screenRotationAnimation =
9989                    mAnimator.getScreenRotationAnimationLocked(displayId);
9990            if (screenRotationAnimation != null) {
9991                screenRotationAnimation.kill();
9992            }
9993
9994            // Check whether the current screen contains any secure content.
9995            boolean isSecure = false;
9996            final WindowList windows = getDefaultWindowListLocked();
9997            final int N = windows.size();
9998            for (int i = 0; i < N; i++) {
9999                WindowState ws = windows.get(i);
10000                if (ws.isOnScreen() && (ws.mAttrs.flags & FLAG_SECURE) != 0) {
10001                    isSecure = true;
10002                    break;
10003                }
10004            }
10005
10006            // TODO(multidisplay): rotation on main screen only.
10007            displayContent.updateDisplayInfo();
10008            screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent,
10009                    mFxSession, inTransaction, mPolicy.isDefaultOrientationForced(), isSecure);
10010            mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
10011        }
10012    }
10013
10014    private void stopFreezingDisplayLocked() {
10015        if (!mDisplayFrozen) {
10016            return;
10017        }
10018
10019        if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen
10020                || mClientFreezingScreen) {
10021            if (DEBUG_ORIENTATION) Slog.d(TAG,
10022                "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig
10023                + ", mAppsFreezingScreen=" + mAppsFreezingScreen
10024                + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen
10025                + ", mClientFreezingScreen=" + mClientFreezingScreen);
10026            return;
10027        }
10028
10029        mDisplayFrozen = false;
10030        mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime);
10031        StringBuilder sb = new StringBuilder(128);
10032        sb.append("Screen frozen for ");
10033        TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb);
10034        if (mLastFinishedFreezeSource != null) {
10035            sb.append(" due to ");
10036            sb.append(mLastFinishedFreezeSource);
10037        }
10038        Slog.i(TAG, sb.toString());
10039        mH.removeMessages(H.APP_FREEZE_TIMEOUT);
10040        mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
10041        if (PROFILE_ORIENTATION) {
10042            Debug.stopMethodTracing();
10043        }
10044
10045        boolean updateRotation = false;
10046
10047        final DisplayContent displayContent = getDefaultDisplayContentLocked();
10048        final int displayId = displayContent.getDisplayId();
10049        ScreenRotationAnimation screenRotationAnimation =
10050                mAnimator.getScreenRotationAnimationLocked(displayId);
10051        if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
10052                && screenRotationAnimation.hasScreenshot()) {
10053            if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation");
10054            // TODO(multidisplay): rotation on main screen only.
10055            DisplayInfo displayInfo = displayContent.getDisplayInfo();
10056            // Get rotation animation again, with new top window
10057            boolean isDimming = displayContent.isDimming();
10058            if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) {
10059                mExitAnimId = mEnterAnimId = 0;
10060            }
10061            if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
10062                    mTransitionAnimationScale, displayInfo.logicalWidth,
10063                        displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) {
10064                scheduleAnimationLocked();
10065            } else {
10066                screenRotationAnimation.kill();
10067                screenRotationAnimation = null;
10068                mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
10069                updateRotation = true;
10070            }
10071        } else {
10072            if (screenRotationAnimation != null) {
10073                screenRotationAnimation.kill();
10074                screenRotationAnimation = null;
10075                mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
10076            }
10077            updateRotation = true;
10078        }
10079
10080        mInputMonitor.thawInputDispatchingLw();
10081
10082        boolean configChanged;
10083
10084        // While the display is frozen we don't re-compute the orientation
10085        // to avoid inconsistent states.  However, something interesting
10086        // could have actually changed during that time so re-evaluate it
10087        // now to catch that.
10088        configChanged = updateOrientationFromAppTokensLocked(false);
10089
10090        // A little kludge: a lot could have happened while the
10091        // display was frozen, so now that we are coming back we
10092        // do a gc so that any remote references the system
10093        // processes holds on others can be released if they are
10094        // no longer needed.
10095        mH.removeMessages(H.FORCE_GC);
10096        mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000);
10097
10098        mScreenFrozenLock.release();
10099
10100        if (updateRotation) {
10101            if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
10102            configChanged |= updateRotationUncheckedLocked(false);
10103        }
10104
10105        if (configChanged) {
10106            mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
10107        }
10108    }
10109
10110    static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps,
10111            DisplayMetrics dm) {
10112        if (index < tokens.length) {
10113            String str = tokens[index];
10114            if (str != null && str.length() > 0) {
10115                try {
10116                    int val = Integer.parseInt(str);
10117                    return val;
10118                } catch (Exception e) {
10119                }
10120            }
10121        }
10122        if (defUnits == TypedValue.COMPLEX_UNIT_PX) {
10123            return defDps;
10124        }
10125        int val = (int)TypedValue.applyDimension(defUnits, defDps, dm);
10126        return val;
10127    }
10128
10129    void createWatermarkInTransaction() {
10130        if (mWatermark != null) {
10131            return;
10132        }
10133
10134        File file = new File("/system/etc/setup.conf");
10135        FileInputStream in = null;
10136        DataInputStream ind = null;
10137        try {
10138            in = new FileInputStream(file);
10139            ind = new DataInputStream(in);
10140            String line = ind.readLine();
10141            if (line != null) {
10142                String[] toks = line.split("%");
10143                if (toks != null && toks.length > 0) {
10144                    mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(),
10145                            mRealDisplayMetrics, mFxSession, toks);
10146                }
10147            }
10148        } catch (FileNotFoundException e) {
10149        } catch (IOException e) {
10150        } finally {
10151            if (ind != null) {
10152                try {
10153                    ind.close();
10154                } catch (IOException e) {
10155                }
10156            } else if (in != null) {
10157                try {
10158                    in.close();
10159                } catch (IOException e) {
10160                }
10161            }
10162        }
10163    }
10164
10165    @Override
10166    public void statusBarVisibilityChanged(int visibility) {
10167        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
10168                != PackageManager.PERMISSION_GRANTED) {
10169            throw new SecurityException("Caller does not hold permission "
10170                    + android.Manifest.permission.STATUS_BAR);
10171        }
10172
10173        synchronized (mWindowMap) {
10174            mLastStatusBarVisibility = visibility;
10175            visibility = mPolicy.adjustSystemUiVisibilityLw(visibility);
10176            updateStatusBarVisibilityLocked(visibility);
10177        }
10178    }
10179
10180    // TOOD(multidisplay): StatusBar on multiple screens?
10181    void updateStatusBarVisibilityLocked(int visibility) {
10182        mInputManager.setSystemUiVisibility(visibility);
10183        final WindowList windows = getDefaultWindowListLocked();
10184        final int N = windows.size();
10185        for (int i = 0; i < N; i++) {
10186            WindowState ws = windows.get(i);
10187            try {
10188                int curValue = ws.mSystemUiVisibility;
10189                int diff = curValue ^ visibility;
10190                // We are only interested in differences of one of the
10191                // clearable flags...
10192                diff &= View.SYSTEM_UI_CLEARABLE_FLAGS;
10193                // ...if it has actually been cleared.
10194                diff &= ~visibility;
10195                int newValue = (curValue&~diff) | (visibility&diff);
10196                if (newValue != curValue) {
10197                    ws.mSeq++;
10198                    ws.mSystemUiVisibility = newValue;
10199                }
10200                if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) {
10201                    ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq,
10202                            visibility, newValue, diff);
10203                }
10204            } catch (RemoteException e) {
10205                // so sorry
10206            }
10207        }
10208    }
10209
10210    @Override
10211    public void reevaluateStatusBarVisibility() {
10212        synchronized (mWindowMap) {
10213            int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility);
10214            updateStatusBarVisibilityLocked(visibility);
10215            performLayoutAndPlaceSurfacesLocked();
10216        }
10217    }
10218
10219    @Override
10220    public FakeWindow addFakeWindow(Looper looper,
10221            InputEventReceiver.Factory inputEventReceiverFactory,
10222            String name, int windowType, int layoutParamsFlags, int layoutParamsPrivateFlags,
10223            boolean canReceiveKeys, boolean hasFocus, boolean touchFullscreen) {
10224        synchronized (mWindowMap) {
10225            FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputEventReceiverFactory,
10226                    name, windowType,
10227                    layoutParamsFlags, layoutParamsPrivateFlags, canReceiveKeys,
10228                    hasFocus, touchFullscreen);
10229            int i=0;
10230            while (i<mFakeWindows.size()) {
10231                if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) {
10232                    break;
10233                }
10234            }
10235            mFakeWindows.add(i, fw);
10236            mInputMonitor.updateInputWindowsLw(true);
10237            return fw;
10238        }
10239    }
10240
10241    boolean removeFakeWindowLocked(FakeWindow window) {
10242        synchronized (mWindowMap) {
10243            if (mFakeWindows.remove(window)) {
10244                mInputMonitor.updateInputWindowsLw(true);
10245                return true;
10246            }
10247            return false;
10248        }
10249    }
10250
10251    // It is assumed that this method is called only by InputMethodManagerService.
10252    public void saveLastInputMethodWindowForTransition() {
10253        synchronized (mWindowMap) {
10254            // TODO(multidisplay): Pass in the displayID.
10255            DisplayContent displayContent = getDefaultDisplayContentLocked();
10256            if (mInputMethodWindow != null) {
10257                mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget);
10258            }
10259        }
10260    }
10261
10262    public int getInputMethodWindowVisibleHeight() {
10263        synchronized (mWindowMap) {
10264            return mPolicy.getInputMethodWindowVisibleHeightLw();
10265        }
10266    }
10267
10268    @Override
10269    public boolean hasNavigationBar() {
10270        return mPolicy.hasNavigationBar();
10271    }
10272
10273    @Override
10274    public void lockNow(Bundle options) {
10275        mPolicy.lockNow(options);
10276    }
10277
10278    public void showRecentApps() {
10279        mPolicy.showRecentApps();
10280    }
10281
10282    @Override
10283    public boolean isSafeModeEnabled() {
10284        return mSafeMode;
10285    }
10286
10287    @Override
10288    public boolean clearWindowContentFrameStats(IBinder token) {
10289        if (!checkCallingPermission(Manifest.permission.FRAME_STATS,
10290                "clearWindowContentFrameStats()")) {
10291            throw new SecurityException("Requires FRAME_STATS permission");
10292        }
10293        synchronized (mWindowMap) {
10294            WindowState windowState = mWindowMap.get(token);
10295            if (windowState == null) {
10296                return false;
10297            }
10298            SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl;
10299            if (surfaceControl == null) {
10300                return false;
10301            }
10302            return surfaceControl.clearContentFrameStats();
10303        }
10304    }
10305
10306    @Override
10307    public WindowContentFrameStats getWindowContentFrameStats(IBinder token) {
10308        if (!checkCallingPermission(Manifest.permission.FRAME_STATS,
10309                "getWindowContentFrameStats()")) {
10310            throw new SecurityException("Requires FRAME_STATS permission");
10311        }
10312        synchronized (mWindowMap) {
10313            WindowState windowState = mWindowMap.get(token);
10314            if (windowState == null) {
10315                return null;
10316            }
10317            SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl;
10318            if (surfaceControl == null) {
10319                return null;
10320            }
10321            if (mTempWindowRenderStats == null) {
10322                mTempWindowRenderStats = new WindowContentFrameStats();
10323            }
10324            WindowContentFrameStats stats = mTempWindowRenderStats;
10325            if (!surfaceControl.getContentFrameStats(stats)) {
10326                return null;
10327            }
10328            return stats;
10329        }
10330    }
10331
10332    void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) {
10333        pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)");
10334        mPolicy.dump("    ", pw, args);
10335    }
10336
10337    void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) {
10338        pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)");
10339        mAnimator.dumpLocked(pw, "    ", dumpAll);
10340    }
10341
10342    void dumpTokensLocked(PrintWriter pw, boolean dumpAll) {
10343        pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)");
10344        if (mTokenMap.size() > 0) {
10345            pw.println("  All tokens:");
10346            Iterator<WindowToken> it = mTokenMap.values().iterator();
10347            while (it.hasNext()) {
10348                WindowToken token = it.next();
10349                pw.print("  "); pw.print(token);
10350                if (dumpAll) {
10351                    pw.println(':');
10352                    token.dump(pw, "    ");
10353                } else {
10354                    pw.println();
10355                }
10356            }
10357        }
10358        if (mWallpaperTokens.size() > 0) {
10359            pw.println();
10360            pw.println("  Wallpaper tokens:");
10361            for (int i=mWallpaperTokens.size()-1; i>=0; i--) {
10362                WindowToken token = mWallpaperTokens.get(i);
10363                pw.print("  Wallpaper #"); pw.print(i);
10364                        pw.print(' '); pw.print(token);
10365                if (dumpAll) {
10366                    pw.println(':');
10367                    token.dump(pw, "    ");
10368                } else {
10369                    pw.println();
10370                }
10371            }
10372        }
10373        if (mFinishedStarting.size() > 0) {
10374            pw.println();
10375            pw.println("  Finishing start of application tokens:");
10376            for (int i=mFinishedStarting.size()-1; i>=0; i--) {
10377                WindowToken token = mFinishedStarting.get(i);
10378                pw.print("  Finished Starting #"); pw.print(i);
10379                        pw.print(' '); pw.print(token);
10380                if (dumpAll) {
10381                    pw.println(':');
10382                    token.dump(pw, "    ");
10383                } else {
10384                    pw.println();
10385                }
10386            }
10387        }
10388        if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) {
10389            pw.println();
10390            if (mOpeningApps.size() > 0) {
10391                pw.print("  mOpeningApps="); pw.println(mOpeningApps);
10392            }
10393            if (mClosingApps.size() > 0) {
10394                pw.print("  mClosingApps="); pw.println(mClosingApps);
10395            }
10396        }
10397    }
10398
10399    void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) {
10400        pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)");
10401        if (mSessions.size() > 0) {
10402            Iterator<Session> it = mSessions.iterator();
10403            while (it.hasNext()) {
10404                Session s = it.next();
10405                pw.print("  Session "); pw.print(s); pw.println(':');
10406                s.dump(pw, "    ");
10407            }
10408        }
10409    }
10410
10411    void dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll) {
10412        pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)");
10413        if (mDisplayReady) {
10414            final int numDisplays = mDisplayContents.size();
10415            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10416                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
10417                displayContent.dump("  ", pw);
10418            }
10419        } else {
10420            pw.println("  NO DISPLAY");
10421        }
10422    }
10423
10424    void dumpWindowsLocked(PrintWriter pw, boolean dumpAll,
10425            ArrayList<WindowState> windows) {
10426        pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)");
10427        dumpWindowsNoHeaderLocked(pw, dumpAll, windows);
10428    }
10429
10430    void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll,
10431            ArrayList<WindowState> windows) {
10432        final int numDisplays = mDisplayContents.size();
10433        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10434            final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList();
10435            for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10436                final WindowState w = windowList.get(winNdx);
10437                if (windows == null || windows.contains(w)) {
10438                    pw.print("  Window #"); pw.print(winNdx); pw.print(' ');
10439                            pw.print(w); pw.println(":");
10440                    w.dump(pw, "    ", dumpAll || windows != null);
10441                }
10442            }
10443        }
10444        if (mInputMethodDialogs.size() > 0) {
10445            pw.println();
10446            pw.println("  Input method dialogs:");
10447            for (int i=mInputMethodDialogs.size()-1; i>=0; i--) {
10448                WindowState w = mInputMethodDialogs.get(i);
10449                if (windows == null || windows.contains(w)) {
10450                    pw.print("  IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w);
10451                }
10452            }
10453        }
10454        if (mPendingRemove.size() > 0) {
10455            pw.println();
10456            pw.println("  Remove pending for:");
10457            for (int i=mPendingRemove.size()-1; i>=0; i--) {
10458                WindowState w = mPendingRemove.get(i);
10459                if (windows == null || windows.contains(w)) {
10460                    pw.print("  Remove #"); pw.print(i); pw.print(' ');
10461                            pw.print(w);
10462                    if (dumpAll) {
10463                        pw.println(":");
10464                        w.dump(pw, "    ", true);
10465                    } else {
10466                        pw.println();
10467                    }
10468                }
10469            }
10470        }
10471        if (mForceRemoves != null && mForceRemoves.size() > 0) {
10472            pw.println();
10473            pw.println("  Windows force removing:");
10474            for (int i=mForceRemoves.size()-1; i>=0; i--) {
10475                WindowState w = mForceRemoves.get(i);
10476                pw.print("  Removing #"); pw.print(i); pw.print(' ');
10477                        pw.print(w);
10478                if (dumpAll) {
10479                    pw.println(":");
10480                    w.dump(pw, "    ", true);
10481                } else {
10482                    pw.println();
10483                }
10484            }
10485        }
10486        if (mDestroySurface.size() > 0) {
10487            pw.println();
10488            pw.println("  Windows waiting to destroy their surface:");
10489            for (int i=mDestroySurface.size()-1; i>=0; i--) {
10490                WindowState w = mDestroySurface.get(i);
10491                if (windows == null || windows.contains(w)) {
10492                    pw.print("  Destroy #"); pw.print(i); pw.print(' ');
10493                            pw.print(w);
10494                    if (dumpAll) {
10495                        pw.println(":");
10496                        w.dump(pw, "    ", true);
10497                    } else {
10498                        pw.println();
10499                    }
10500                }
10501            }
10502        }
10503        if (mLosingFocus.size() > 0) {
10504            pw.println();
10505            pw.println("  Windows losing focus:");
10506            for (int i=mLosingFocus.size()-1; i>=0; i--) {
10507                WindowState w = mLosingFocus.get(i);
10508                if (windows == null || windows.contains(w)) {
10509                    pw.print("  Losing #"); pw.print(i); pw.print(' ');
10510                            pw.print(w);
10511                    if (dumpAll) {
10512                        pw.println(":");
10513                        w.dump(pw, "    ", true);
10514                    } else {
10515                        pw.println();
10516                    }
10517                }
10518            }
10519        }
10520        if (mResizingWindows.size() > 0) {
10521            pw.println();
10522            pw.println("  Windows waiting to resize:");
10523            for (int i=mResizingWindows.size()-1; i>=0; i--) {
10524                WindowState w = mResizingWindows.get(i);
10525                if (windows == null || windows.contains(w)) {
10526                    pw.print("  Resizing #"); pw.print(i); pw.print(' ');
10527                            pw.print(w);
10528                    if (dumpAll) {
10529                        pw.println(":");
10530                        w.dump(pw, "    ", true);
10531                    } else {
10532                        pw.println();
10533                    }
10534                }
10535            }
10536        }
10537        if (mWaitingForDrawn.size() > 0) {
10538            pw.println();
10539            pw.println("  Clients waiting for these windows to be drawn:");
10540            for (int i=mWaitingForDrawn.size()-1; i>=0; i--) {
10541                Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(i);
10542                pw.print("  Waiting #"); pw.print(i); pw.print(' '); pw.print(pair.first);
10543                        pw.print(": "); pw.println(pair.second);
10544            }
10545        }
10546        pw.println();
10547        pw.print("  mCurConfiguration="); pw.println(this.mCurConfiguration);
10548        pw.print("  mCurrentFocus="); pw.println(mCurrentFocus);
10549        if (mLastFocus != mCurrentFocus) {
10550            pw.print("  mLastFocus="); pw.println(mLastFocus);
10551        }
10552        pw.print("  mFocusedApp="); pw.println(mFocusedApp);
10553        if (mInputMethodTarget != null) {
10554            pw.print("  mInputMethodTarget="); pw.println(mInputMethodTarget);
10555        }
10556        pw.print("  mInTouchMode="); pw.print(mInTouchMode);
10557                pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
10558        pw.print("  mLastDisplayFreezeDuration=");
10559                TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw);
10560                if ( mLastFinishedFreezeSource != null) {
10561                    pw.print(" due to ");
10562                    pw.print(mLastFinishedFreezeSource);
10563                }
10564                pw.println();
10565        if (dumpAll) {
10566            pw.print("  mSystemDecorLayer="); pw.print(mSystemDecorLayer);
10567                    pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString());
10568            if (mLastStatusBarVisibility != 0) {
10569                pw.print("  mLastStatusBarVisibility=0x");
10570                        pw.println(Integer.toHexString(mLastStatusBarVisibility));
10571            }
10572            if (mInputMethodWindow != null) {
10573                pw.print("  mInputMethodWindow="); pw.println(mInputMethodWindow);
10574            }
10575            pw.print("  mWallpaperTarget="); pw.println(mWallpaperTarget);
10576            if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) {
10577                pw.print("  mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget);
10578                pw.print("  mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget);
10579            }
10580            pw.print("  mLastWallpaperX="); pw.print(mLastWallpaperX);
10581                    pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
10582            if (mInputMethodAnimLayerAdjustment != 0 ||
10583                    mWallpaperAnimLayerAdjustment != 0) {
10584                pw.print("  mInputMethodAnimLayerAdjustment=");
10585                        pw.print(mInputMethodAnimLayerAdjustment);
10586                        pw.print("  mWallpaperAnimLayerAdjustment=");
10587                        pw.println(mWallpaperAnimLayerAdjustment);
10588            }
10589            pw.print("  mSystemBooted="); pw.print(mSystemBooted);
10590                    pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
10591            if (needsLayout()) {
10592                pw.print("  layoutNeeded on displays=");
10593                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10594                    final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
10595                    if (displayContent.layoutNeeded) {
10596                        pw.print(displayContent.getDisplayId());
10597                    }
10598                }
10599                pw.println();
10600            }
10601            pw.print("  mTransactionSequence="); pw.println(mTransactionSequence);
10602            pw.print("  mDisplayFrozen="); pw.print(mDisplayFrozen);
10603                    pw.print(" windows="); pw.print(mWindowsFreezingScreen);
10604                    pw.print(" client="); pw.print(mClientFreezingScreen);
10605                    pw.print(" apps="); pw.print(mAppsFreezingScreen);
10606                    pw.print(" waitingForConfig="); pw.println(mWaitingForConfig);
10607            pw.print("  mRotation="); pw.print(mRotation);
10608                    pw.print(" mAltOrientation="); pw.println(mAltOrientation);
10609            pw.print("  mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation);
10610                    pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation);
10611            pw.print("  mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount);
10612            pw.print("  mWindowAnimationScale="); pw.print(mWindowAnimationScale);
10613                    pw.print(" mTransitionWindowAnimationScale="); pw.print(mTransitionAnimationScale);
10614                    pw.print(" mAnimatorDurationScale="); pw.println(mAnimatorDurationScale);
10615            pw.print("  mTraversalScheduled="); pw.println(mTraversalScheduled);
10616            pw.print("  mStartingIconInTransition="); pw.print(mStartingIconInTransition);
10617                    pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
10618            pw.println("  mLayoutToAnim:");
10619            mAppTransition.dump(pw);
10620        }
10621    }
10622
10623    boolean dumpWindows(PrintWriter pw, String name, String[] args,
10624            int opti, boolean dumpAll) {
10625        WindowList windows = new WindowList();
10626        if ("visible".equals(name)) {
10627            synchronized(mWindowMap) {
10628                final int numDisplays = mDisplayContents.size();
10629                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10630                    final WindowList windowList =
10631                            mDisplayContents.valueAt(displayNdx).getWindowList();
10632                    for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10633                        final WindowState w = windowList.get(winNdx);
10634                        if (w.mWinAnimator.mSurfaceShown) {
10635                            windows.add(w);
10636                        }
10637                    }
10638                }
10639            }
10640        } else {
10641            int objectId = 0;
10642            // See if this is an object ID.
10643            try {
10644                objectId = Integer.parseInt(name, 16);
10645                name = null;
10646            } catch (RuntimeException e) {
10647            }
10648            synchronized(mWindowMap) {
10649                final int numDisplays = mDisplayContents.size();
10650                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10651                    final WindowList windowList =
10652                            mDisplayContents.valueAt(displayNdx).getWindowList();
10653                    for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10654                        final WindowState w = windowList.get(winNdx);
10655                        if (name != null) {
10656                            if (w.mAttrs.getTitle().toString().contains(name)) {
10657                                windows.add(w);
10658                            }
10659                        } else if (System.identityHashCode(w) == objectId) {
10660                            windows.add(w);
10661                        }
10662                    }
10663                }
10664            }
10665        }
10666
10667        if (windows.size() <= 0) {
10668            return false;
10669        }
10670
10671        synchronized(mWindowMap) {
10672            dumpWindowsLocked(pw, dumpAll, windows);
10673        }
10674        return true;
10675    }
10676
10677    void dumpLastANRLocked(PrintWriter pw) {
10678        pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)");
10679        if (mLastANRState == null) {
10680            pw.println("  <no ANR has occurred since boot>");
10681        } else {
10682            pw.println(mLastANRState);
10683        }
10684    }
10685
10686    /**
10687     * Saves information about the state of the window manager at
10688     * the time an ANR occurred before anything else in the system changes
10689     * in response.
10690     *
10691     * @param appWindowToken The application that ANR'd, may be null.
10692     * @param windowState The window that ANR'd, may be null.
10693     * @param reason The reason for the ANR, may be null.
10694     */
10695    public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState,
10696            String reason) {
10697        StringWriter sw = new StringWriter();
10698        PrintWriter pw = new FastPrintWriter(sw, false, 1024);
10699        pw.println("  ANR time: " + DateFormat.getInstance().format(new Date()));
10700        if (appWindowToken != null) {
10701            pw.println("  Application at fault: " + appWindowToken.stringName);
10702        }
10703        if (windowState != null) {
10704            pw.println("  Window at fault: " + windowState.mAttrs.getTitle());
10705        }
10706        if (reason != null) {
10707            pw.println("  Reason: " + reason);
10708        }
10709        pw.println();
10710        dumpWindowsNoHeaderLocked(pw, true, null);
10711        pw.close();
10712        mLastANRState = sw.toString();
10713    }
10714
10715    @Override
10716    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
10717        if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
10718                != PackageManager.PERMISSION_GRANTED) {
10719            pw.println("Permission Denial: can't dump WindowManager from from pid="
10720                    + Binder.getCallingPid()
10721                    + ", uid=" + Binder.getCallingUid());
10722            return;
10723        }
10724
10725        boolean dumpAll = false;
10726
10727        int opti = 0;
10728        while (opti < args.length) {
10729            String opt = args[opti];
10730            if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
10731                break;
10732            }
10733            opti++;
10734            if ("-a".equals(opt)) {
10735                dumpAll = true;
10736            } else if ("-h".equals(opt)) {
10737                pw.println("Window manager dump options:");
10738                pw.println("  [-a] [-h] [cmd] ...");
10739                pw.println("  cmd may be one of:");
10740                pw.println("    l[astanr]: last ANR information");
10741                pw.println("    p[policy]: policy state");
10742                pw.println("    a[animator]: animator state");
10743                pw.println("    s[essions]: active sessions");
10744                pw.println("    d[isplays]: active display contents");
10745                pw.println("    t[okens]: token list");
10746                pw.println("    w[indows]: window list");
10747                pw.println("  cmd may also be a NAME to dump windows.  NAME may");
10748                pw.println("    be a partial substring in a window name, a");
10749                pw.println("    Window hex object identifier, or");
10750                pw.println("    \"all\" for all windows, or");
10751                pw.println("    \"visible\" for the visible windows.");
10752                pw.println("  -a: include all available server state.");
10753                return;
10754            } else {
10755                pw.println("Unknown argument: " + opt + "; use -h for help");
10756            }
10757        }
10758
10759        // Is the caller requesting to dump a particular piece of data?
10760        if (opti < args.length) {
10761            String cmd = args[opti];
10762            opti++;
10763            if ("lastanr".equals(cmd) || "l".equals(cmd)) {
10764                synchronized(mWindowMap) {
10765                    dumpLastANRLocked(pw);
10766                }
10767                return;
10768            } else if ("policy".equals(cmd) || "p".equals(cmd)) {
10769                synchronized(mWindowMap) {
10770                    dumpPolicyLocked(pw, args, true);
10771                }
10772                return;
10773            } else if ("animator".equals(cmd) || "a".equals(cmd)) {
10774                synchronized(mWindowMap) {
10775                    dumpAnimatorLocked(pw, args, true);
10776                }
10777                return;
10778            } else if ("sessions".equals(cmd) || "s".equals(cmd)) {
10779                synchronized(mWindowMap) {
10780                    dumpSessionsLocked(pw, true);
10781                }
10782                return;
10783            } else if ("displays".equals(cmd) || "d".equals(cmd)) {
10784                synchronized(mWindowMap) {
10785                    dumpDisplayContentsLocked(pw, true);
10786                }
10787                return;
10788            } else if ("tokens".equals(cmd) || "t".equals(cmd)) {
10789                synchronized(mWindowMap) {
10790                    dumpTokensLocked(pw, true);
10791                }
10792                return;
10793            } else if ("windows".equals(cmd) || "w".equals(cmd)) {
10794                synchronized(mWindowMap) {
10795                    dumpWindowsLocked(pw, true, null);
10796                }
10797                return;
10798            } else if ("all".equals(cmd) || "a".equals(cmd)) {
10799                synchronized(mWindowMap) {
10800                    dumpWindowsLocked(pw, true, null);
10801                }
10802                return;
10803            } else {
10804                // Dumping a single name?
10805                if (!dumpWindows(pw, cmd, args, opti, dumpAll)) {
10806                    pw.println("Bad window command, or no windows match: " + cmd);
10807                    pw.println("Use -h for help.");
10808                }
10809                return;
10810            }
10811        }
10812
10813        synchronized(mWindowMap) {
10814            pw.println();
10815            if (dumpAll) {
10816                pw.println("-------------------------------------------------------------------------------");
10817            }
10818            dumpLastANRLocked(pw);
10819            pw.println();
10820            if (dumpAll) {
10821                pw.println("-------------------------------------------------------------------------------");
10822            }
10823            dumpPolicyLocked(pw, args, dumpAll);
10824            pw.println();
10825            if (dumpAll) {
10826                pw.println("-------------------------------------------------------------------------------");
10827            }
10828            dumpAnimatorLocked(pw, args, dumpAll);
10829            pw.println();
10830            if (dumpAll) {
10831                pw.println("-------------------------------------------------------------------------------");
10832            }
10833            dumpSessionsLocked(pw, dumpAll);
10834            pw.println();
10835            if (dumpAll) {
10836                pw.println("-------------------------------------------------------------------------------");
10837            }
10838            dumpDisplayContentsLocked(pw, dumpAll);
10839            pw.println();
10840            if (dumpAll) {
10841                pw.println("-------------------------------------------------------------------------------");
10842            }
10843            dumpTokensLocked(pw, dumpAll);
10844            pw.println();
10845            if (dumpAll) {
10846                pw.println("-------------------------------------------------------------------------------");
10847            }
10848            dumpWindowsLocked(pw, dumpAll, null);
10849        }
10850    }
10851
10852    // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection).
10853    @Override
10854    public void monitor() {
10855        synchronized (mWindowMap) { }
10856    }
10857
10858    public interface OnHardKeyboardStatusChangeListener {
10859        public void onHardKeyboardStatusChange(boolean available, boolean enabled);
10860    }
10861
10862    void debugLayoutRepeats(final String msg, int pendingLayoutChanges) {
10863        if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) {
10864            Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" +
10865                    Integer.toHexString(pendingLayoutChanges));
10866        }
10867    }
10868
10869    private DisplayContent newDisplayContentLocked(final Display display) {
10870        DisplayContent displayContent = new DisplayContent(display, this);
10871        final int displayId = display.getDisplayId();
10872        if (DEBUG_DISPLAY) Slog.v(TAG, "Adding display=" + display);
10873        mDisplayContents.put(displayId, displayContent);
10874
10875        DisplayInfo displayInfo = displayContent.getDisplayInfo();
10876        final Rect rect = new Rect();
10877        mDisplaySettings.getOverscanLocked(displayInfo.name, rect);
10878        synchronized (displayContent.mDisplaySizeLock) {
10879            displayInfo.overscanLeft = rect.left;
10880            displayInfo.overscanTop = rect.top;
10881            displayInfo.overscanRight = rect.right;
10882            displayInfo.overscanBottom = rect.bottom;
10883            mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
10884                    displayId, displayInfo);
10885        }
10886        configureDisplayPolicyLocked(displayContent);
10887
10888        // TODO: Create an input channel for each display with touch capability.
10889        if (displayId == Display.DEFAULT_DISPLAY) {
10890            displayContent.mTapDetector = new StackTapPointerEventListener(this, displayContent);
10891            registerPointerEventListener(displayContent.mTapDetector);
10892        }
10893
10894        return displayContent;
10895    }
10896
10897    public void createDisplayContentLocked(final Display display) {
10898        if (display == null) {
10899            throw new IllegalArgumentException("getDisplayContent: display must not be null");
10900        }
10901        getDisplayContentLocked(display.getDisplayId());
10902    }
10903
10904    /**
10905     * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if
10906     * there is a Display for the displayId.
10907     * @param displayId The display the caller is interested in.
10908     * @return The DisplayContent associated with displayId or null if there is no Display for it.
10909     */
10910    public DisplayContent getDisplayContentLocked(final int displayId) {
10911        DisplayContent displayContent = mDisplayContents.get(displayId);
10912        if (displayContent == null) {
10913            final Display display = mDisplayManager.getDisplay(displayId);
10914            if (display != null) {
10915                displayContent = newDisplayContentLocked(display);
10916            }
10917        }
10918        return displayContent;
10919    }
10920
10921    // There is an inherent assumption that this will never return null.
10922    public DisplayContent getDefaultDisplayContentLocked() {
10923        return getDisplayContentLocked(Display.DEFAULT_DISPLAY);
10924    }
10925
10926    public WindowList getDefaultWindowListLocked() {
10927        return getDefaultDisplayContentLocked().getWindowList();
10928    }
10929
10930    public DisplayInfo getDefaultDisplayInfoLocked() {
10931        return getDefaultDisplayContentLocked().getDisplayInfo();
10932    }
10933
10934    /**
10935     * Return the list of WindowStates associated on the passed display.
10936     * @param display The screen to return windows from.
10937     * @return The list of WindowStates on the screen, or null if the there is no screen.
10938     */
10939    public WindowList getWindowListLocked(final Display display) {
10940        return getWindowListLocked(display.getDisplayId());
10941    }
10942
10943    /**
10944     * Return the list of WindowStates associated on the passed display.
10945     * @param displayId The screen to return windows from.
10946     * @return The list of WindowStates on the screen, or null if the there is no screen.
10947     */
10948    public WindowList getWindowListLocked(final int displayId) {
10949        final DisplayContent displayContent = getDisplayContentLocked(displayId);
10950        return displayContent != null ? displayContent.getWindowList() : null;
10951    }
10952
10953    public void onDisplayAdded(int displayId) {
10954        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0));
10955    }
10956
10957    public void handleDisplayAdded(int displayId) {
10958        synchronized (mWindowMap) {
10959            final Display display = mDisplayManager.getDisplay(displayId);
10960            if (display != null) {
10961                createDisplayContentLocked(display);
10962                displayReady(displayId);
10963            }
10964        }
10965    }
10966
10967    public void onDisplayRemoved(int displayId) {
10968        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0));
10969    }
10970
10971    private void handleDisplayRemovedLocked(int displayId) {
10972        final DisplayContent displayContent = getDisplayContentLocked(displayId);
10973        if (displayContent != null) {
10974            if (displayContent.isAnimating()) {
10975                displayContent.mDeferredRemoval = true;
10976                return;
10977            }
10978            if (DEBUG_DISPLAY) Slog.v(TAG, "Removing display=" + displayContent);
10979            mDisplayContents.delete(displayId);
10980            displayContent.close();
10981            if (displayId == Display.DEFAULT_DISPLAY) {
10982                unregisterPointerEventListener(displayContent.mTapDetector);
10983            }
10984        }
10985        mAnimator.removeDisplayLocked(displayId);
10986    }
10987
10988    public void onDisplayChanged(int displayId) {
10989        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0));
10990    }
10991
10992    private void handleDisplayChangedLocked(int displayId) {
10993        final DisplayContent displayContent = getDisplayContentLocked(displayId);
10994        if (displayContent != null) {
10995            displayContent.updateDisplayInfo();
10996        }
10997    }
10998
10999    @Override
11000    public Object getWindowManagerLock() {
11001        return mWindowMap;
11002    }
11003
11004    private final class LocalService extends WindowManagerInternal {
11005        @Override
11006        public void requestTraversalFromDisplayManager() {
11007            requestTraversal();
11008        }
11009
11010        @Override
11011        public void setMagnificationSpec(MagnificationSpec spec) {
11012            synchronized (mWindowMap) {
11013                if (mAccessibilityController != null) {
11014                    mAccessibilityController.setMagnificationSpecLocked(spec);
11015                } else {
11016                    throw new IllegalStateException("Magnification callbacks not set!");
11017                }
11018            }
11019            if (Binder.getCallingPid() != android.os.Process.myPid()) {
11020                spec.recycle();
11021            }
11022        }
11023
11024        @Override
11025        public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) {
11026            synchronized (mWindowMap) {
11027                WindowState windowState = mWindowMap.get(windowToken);
11028                if (windowState == null) {
11029                    return null;
11030                }
11031                MagnificationSpec spec = null;
11032                if (mAccessibilityController != null) {
11033                    spec = mAccessibilityController.getMagnificationSpecForWindowLocked(windowState);
11034                }
11035                if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) {
11036                    return null;
11037                }
11038                spec = (spec == null) ? MagnificationSpec.obtain() : MagnificationSpec.obtain(spec);
11039                spec.scale *= windowState.mGlobalScale;
11040                return spec;
11041            }
11042        }
11043
11044        @Override
11045        public void setMagnificationCallbacks(MagnificationCallbacks callbacks) {
11046            synchronized (mWindowMap) {
11047                if (mAccessibilityController == null) {
11048                    mAccessibilityController = new AccessibilityController(
11049                            WindowManagerService.this);
11050                }
11051                mAccessibilityController.setMagnificationCallbacksLocked(callbacks);
11052                if (!mAccessibilityController.hasCallbacksLocked()) {
11053                     mAccessibilityController = null;
11054                }
11055            }
11056        }
11057
11058        @Override
11059        public void setWindowsForAccessibilityCallback(WindowsForAccessibilityCallback callback) {
11060            synchronized (mWindowMap) {
11061                if (mAccessibilityController == null) {
11062                    mAccessibilityController = new AccessibilityController(
11063                            WindowManagerService.this);
11064                }
11065                mAccessibilityController.setWindowsForAccessibilityCallback(callback);
11066                if (!mAccessibilityController.hasCallbacksLocked()) {
11067                     mAccessibilityController = null;
11068                }
11069            }
11070        }
11071
11072        @Override
11073        public void setInputFilter(IInputFilter filter) {
11074            mInputManager.setInputFilter(filter);
11075        }
11076
11077        @Override
11078        public IBinder getFocusedWindowToken() {
11079            synchronized (mWindowMap) {
11080                WindowState windowState = getFocusedWindowLocked();
11081                if (windowState != null) {
11082                    return windowState.mClient.asBinder();
11083                }
11084                return null;
11085            }
11086        }
11087
11088        @Override
11089        public boolean isKeyguardLocked() {
11090            return isKeyguardLocked();
11091        }
11092
11093        @Override
11094        public void getWindowFrame(IBinder token, Rect outBounds) {
11095            synchronized (mWindowMap) {
11096                WindowState windowState = mWindowMap.get(token);
11097                if (windowState != null) {
11098                    outBounds.set(windowState.mFrame);
11099                } else {
11100                    outBounds.setEmpty();
11101                }
11102            }
11103        }
11104    }
11105}
11106