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