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