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