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