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