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