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