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