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