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