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