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