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