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