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