WindowManagerService.java revision dc548483ae90ba26ad9e2e2cb79f4673140edb49
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                    displayContent.detachStack(stack);
4921                    stack.detachDisplay();
4922                }
4923            }
4924        }
4925    }
4926
4927    public void removeTask(int taskId) {
4928        synchronized (mWindowMap) {
4929            Task task = mTaskIdToTask.get(taskId);
4930            if (task == null) {
4931                if (DEBUG_STACK) Slog.i(TAG, "removeTask: could not find taskId=" + taskId);
4932                return;
4933            }
4934            final TaskStack stack = task.mStack;
4935            EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, taskId, "removeTask");
4936            stack.removeTask(task);
4937        }
4938    }
4939
4940    public void addTask(int taskId, int stackId, boolean toTop) {
4941        synchronized (mWindowMap) {
4942            Task task = mTaskIdToTask.get(taskId);
4943            if (task == null) {
4944                return;
4945            }
4946            TaskStack stack = mStackIdToStack.get(stackId);
4947            stack.addTask(task, toTop);
4948            final DisplayContent displayContent = stack.getDisplayContent();
4949            displayContent.layoutNeeded = true;
4950            performLayoutAndPlaceSurfacesLocked();
4951        }
4952    }
4953
4954    public void resizeStack(int stackId, Rect bounds) {
4955        synchronized (mWindowMap) {
4956            final TaskStack stack = mStackIdToStack.get(stackId);
4957            if (stack == null) {
4958                throw new IllegalArgumentException("resizeStack: stackId " + stackId
4959                        + " not found.");
4960            }
4961            if (stack.setBounds(bounds)) {
4962                stack.getDisplayContent().layoutNeeded = true;
4963                performLayoutAndPlaceSurfacesLocked();
4964            }
4965        }
4966    }
4967
4968    public void getStackBounds(int stackId, Rect bounds) {
4969        final TaskStack stack = mStackIdToStack.get(stackId);
4970        if (stack != null) {
4971            stack.getBounds(bounds);
4972            return;
4973        }
4974        bounds.setEmpty();
4975    }
4976
4977    // -------------------------------------------------------------
4978    // Misc IWindowSession methods
4979    // -------------------------------------------------------------
4980
4981    @Override
4982    public void startFreezingScreen(int exitAnim, int enterAnim) {
4983        if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
4984                "startFreezingScreen()")) {
4985            throw new SecurityException("Requires FREEZE_SCREEN permission");
4986        }
4987
4988        synchronized(mWindowMap) {
4989            if (!mClientFreezingScreen) {
4990                mClientFreezingScreen = true;
4991                final long origId = Binder.clearCallingIdentity();
4992                try {
4993                    startFreezingDisplayLocked(false, exitAnim, enterAnim);
4994                    mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
4995                    mH.sendEmptyMessageDelayed(H.CLIENT_FREEZE_TIMEOUT, 5000);
4996                } finally {
4997                    Binder.restoreCallingIdentity(origId);
4998                }
4999            }
5000        }
5001    }
5002
5003    @Override
5004    public void stopFreezingScreen() {
5005        if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
5006                "stopFreezingScreen()")) {
5007            throw new SecurityException("Requires FREEZE_SCREEN permission");
5008        }
5009
5010        synchronized(mWindowMap) {
5011            if (mClientFreezingScreen) {
5012                mClientFreezingScreen = false;
5013                mLastFinishedFreezeSource = "client";
5014                final long origId = Binder.clearCallingIdentity();
5015                try {
5016                    stopFreezingDisplayLocked();
5017                } finally {
5018                    Binder.restoreCallingIdentity(origId);
5019                }
5020            }
5021        }
5022    }
5023
5024    @Override
5025    public void disableKeyguard(IBinder token, String tag) {
5026        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5027            != PackageManager.PERMISSION_GRANTED) {
5028            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5029        }
5030
5031        mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
5032                KeyguardDisableHandler.KEYGUARD_DISABLE, new Pair<IBinder, String>(token, tag)));
5033    }
5034
5035    @Override
5036    public void reenableKeyguard(IBinder token) {
5037        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5038            != PackageManager.PERMISSION_GRANTED) {
5039            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5040        }
5041
5042        mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
5043                KeyguardDisableHandler.KEYGUARD_REENABLE, token));
5044    }
5045
5046    /**
5047     * @see android.app.KeyguardManager#exitKeyguardSecurely
5048     */
5049    @Override
5050    public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) {
5051        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5052            != PackageManager.PERMISSION_GRANTED) {
5053            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5054        }
5055        mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() {
5056            @Override
5057            public void onKeyguardExitResult(boolean success) {
5058                try {
5059                    callback.onKeyguardExitResult(success);
5060                } catch (RemoteException e) {
5061                    // Client has died, we don't care.
5062                }
5063            }
5064        });
5065    }
5066
5067    @Override
5068    public boolean inKeyguardRestrictedInputMode() {
5069        return mPolicy.inKeyguardRestrictedKeyInputMode();
5070    }
5071
5072    @Override
5073    public boolean isKeyguardLocked() {
5074        return mPolicy.isKeyguardLocked();
5075    }
5076
5077    @Override
5078    public boolean isKeyguardSecure() {
5079        return mPolicy.isKeyguardSecure();
5080    }
5081
5082    @Override
5083    public void dismissKeyguard() {
5084        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5085                != PackageManager.PERMISSION_GRANTED) {
5086            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5087        }
5088        synchronized(mWindowMap) {
5089            mPolicy.dismissKeyguardLw();
5090        }
5091    }
5092
5093    @Override
5094    public void closeSystemDialogs(String reason) {
5095        synchronized(mWindowMap) {
5096            final int numDisplays = mDisplayContents.size();
5097            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5098                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
5099                final int numWindows = windows.size();
5100                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
5101                    final WindowState w = windows.get(winNdx);
5102                    if (w.mHasSurface) {
5103                        try {
5104                            w.mClient.closeSystemDialogs(reason);
5105                        } catch (RemoteException e) {
5106                        }
5107                    }
5108                }
5109            }
5110        }
5111    }
5112
5113    static float fixScale(float scale) {
5114        if (scale < 0) scale = 0;
5115        else if (scale > 20) scale = 20;
5116        return Math.abs(scale);
5117    }
5118
5119    @Override
5120    public void setAnimationScale(int which, float scale) {
5121        if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
5122                "setAnimationScale()")) {
5123            throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
5124        }
5125
5126        scale = fixScale(scale);
5127        switch (which) {
5128            case 0: mWindowAnimationScale = scale; break;
5129            case 1: mTransitionAnimationScale = scale; break;
5130            case 2: mAnimatorDurationScale = scale; break;
5131        }
5132
5133        // Persist setting
5134        mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
5135    }
5136
5137    @Override
5138    public void setAnimationScales(float[] scales) {
5139        if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
5140                "setAnimationScale()")) {
5141            throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
5142        }
5143
5144        if (scales != null) {
5145            if (scales.length >= 1) {
5146                mWindowAnimationScale = fixScale(scales[0]);
5147            }
5148            if (scales.length >= 2) {
5149                mTransitionAnimationScale = fixScale(scales[1]);
5150            }
5151            if (scales.length >= 3) {
5152                setAnimatorDurationScale(fixScale(scales[2]));
5153            }
5154        }
5155
5156        // Persist setting
5157        mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
5158    }
5159
5160    private void setAnimatorDurationScale(float scale) {
5161        mAnimatorDurationScale = scale;
5162        ValueAnimator.setDurationScale(scale);
5163    }
5164
5165    @Override
5166    public float getAnimationScale(int which) {
5167        switch (which) {
5168            case 0: return mWindowAnimationScale;
5169            case 1: return mTransitionAnimationScale;
5170            case 2: return mAnimatorDurationScale;
5171        }
5172        return 0;
5173    }
5174
5175    @Override
5176    public float[] getAnimationScales() {
5177        return new float[] { mWindowAnimationScale, mTransitionAnimationScale,
5178                mAnimatorDurationScale };
5179    }
5180
5181    @Override
5182    public void registerPointerEventListener(PointerEventListener listener) {
5183        mPointerEventDispatcher.registerInputEventListener(listener);
5184    }
5185
5186    @Override
5187    public void unregisterPointerEventListener(PointerEventListener listener) {
5188        mPointerEventDispatcher.unregisterInputEventListener(listener);
5189    }
5190
5191    // Called by window manager policy. Not exposed externally.
5192    @Override
5193    public int getLidState() {
5194        int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY,
5195                InputManagerService.SW_LID);
5196        if (sw > 0) {
5197            // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL.
5198            return LID_CLOSED;
5199        } else if (sw == 0) {
5200            // Switch state: AKEY_STATE_UP.
5201            return LID_OPEN;
5202        } else {
5203            // Switch state: AKEY_STATE_UNKNOWN.
5204            return LID_ABSENT;
5205        }
5206    }
5207
5208    // Called by window manager policy.  Not exposed externally.
5209    @Override
5210    public void switchKeyboardLayout(int deviceId, int direction) {
5211        mInputManager.switchKeyboardLayout(deviceId, direction);
5212    }
5213
5214    // Called by window manager policy.  Not exposed externally.
5215    @Override
5216    public void shutdown(boolean confirm) {
5217        ShutdownThread.shutdown(mContext, confirm);
5218    }
5219
5220    // Called by window manager policy.  Not exposed externally.
5221    @Override
5222    public void rebootSafeMode(boolean confirm) {
5223        ShutdownThread.rebootSafeMode(mContext, confirm);
5224    }
5225
5226    @Override
5227    public void setInputFilter(IInputFilter filter) {
5228        if (!checkCallingPermission(android.Manifest.permission.FILTER_EVENTS, "setInputFilter()")) {
5229            throw new SecurityException("Requires FILTER_EVENTS permission");
5230        }
5231        mInputManager.setInputFilter(filter);
5232    }
5233
5234    @Override
5235    public void setTouchExplorationEnabled(boolean enabled) {
5236        mPolicy.setTouchExplorationEnabled(enabled);
5237    }
5238
5239    public void setCurrentUser(final int newUserId) {
5240        synchronized (mWindowMap) {
5241            int oldUserId = mCurrentUserId;
5242            mCurrentUserId = newUserId;
5243            mAppTransition.setCurrentUser(newUserId);
5244            mPolicy.setCurrentUserLw(newUserId);
5245
5246            // Hide windows that should not be seen by the new user.
5247            final int numDisplays = mDisplayContents.size();
5248            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5249                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
5250                displayContent.switchUserStacks(newUserId);
5251                rebuildAppWindowListLocked(displayContent);
5252            }
5253            performLayoutAndPlaceSurfacesLocked();
5254        }
5255    }
5256
5257    public void enableScreenAfterBoot() {
5258        synchronized(mWindowMap) {
5259            if (DEBUG_BOOT) {
5260                RuntimeException here = new RuntimeException("here");
5261                here.fillInStackTrace();
5262                Slog.i(TAG, "enableScreenAfterBoot: mDisplayEnabled=" + mDisplayEnabled
5263                        + " mForceDisplayEnabled=" + mForceDisplayEnabled
5264                        + " mShowingBootMessages=" + mShowingBootMessages
5265                        + " mSystemBooted=" + mSystemBooted, here);
5266            }
5267            if (mSystemBooted) {
5268                return;
5269            }
5270            mSystemBooted = true;
5271            hideBootMessagesLocked();
5272            // If the screen still doesn't come up after 30 seconds, give
5273            // up and turn it on.
5274            mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30*1000);
5275        }
5276
5277        mPolicy.systemBooted();
5278
5279        performEnableScreen();
5280    }
5281
5282    void enableScreenIfNeededLocked() {
5283        if (DEBUG_BOOT) {
5284            RuntimeException here = new RuntimeException("here");
5285            here.fillInStackTrace();
5286            Slog.i(TAG, "enableScreenIfNeededLocked: mDisplayEnabled=" + mDisplayEnabled
5287                    + " mForceDisplayEnabled=" + mForceDisplayEnabled
5288                    + " mShowingBootMessages=" + mShowingBootMessages
5289                    + " mSystemBooted=" + mSystemBooted, here);
5290        }
5291        if (mDisplayEnabled) {
5292            return;
5293        }
5294        if (!mSystemBooted && !mShowingBootMessages) {
5295            return;
5296        }
5297        mH.sendEmptyMessage(H.ENABLE_SCREEN);
5298    }
5299
5300    public void performBootTimeout() {
5301        synchronized(mWindowMap) {
5302            if (mDisplayEnabled) {
5303                return;
5304            }
5305            Slog.w(TAG, "***** BOOT TIMEOUT: forcing display enabled");
5306            mForceDisplayEnabled = true;
5307        }
5308        performEnableScreen();
5309    }
5310
5311    public void performEnableScreen() {
5312        synchronized(mWindowMap) {
5313            if (DEBUG_BOOT) {
5314                RuntimeException here = new RuntimeException("here");
5315                here.fillInStackTrace();
5316                Slog.i(TAG, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled
5317                        + " mForceDisplayEnabled=" + mForceDisplayEnabled
5318                        + " mShowingBootMessages=" + mShowingBootMessages
5319                        + " mSystemBooted=" + mSystemBooted
5320                        + " mOnlyCore=" + mOnlyCore, here);
5321            }
5322            if (mDisplayEnabled) {
5323                return;
5324            }
5325            if (!mSystemBooted && !mShowingBootMessages) {
5326                return;
5327            }
5328
5329            if (!mForceDisplayEnabled) {
5330                // Don't enable the screen until all existing windows
5331                // have been drawn.
5332                boolean haveBootMsg = false;
5333                boolean haveApp = false;
5334                // if the wallpaper service is disabled on the device, we're never going to have
5335                // wallpaper, don't bother waiting for it
5336                boolean haveWallpaper = false;
5337                boolean wallpaperEnabled = mContext.getResources().getBoolean(
5338                        com.android.internal.R.bool.config_enableWallpaperService)
5339                        && !mOnlyCore;
5340                boolean haveKeyguard = true;
5341                // TODO(multidisplay): Expand to all displays?
5342                final WindowList windows = getDefaultWindowListLocked();
5343                final int N = windows.size();
5344                for (int i=0; i<N; i++) {
5345                    WindowState w = windows.get(i);
5346                    if (w.mAttrs.type == TYPE_KEYGUARD) {
5347                        // Only if there is a keyguard attached to the window manager
5348                        // will we consider ourselves as having a keyguard.  If it
5349                        // isn't attached, we don't know if it wants to be shown or
5350                        // hidden.  If it is attached, we will say we have a keyguard
5351                        // if the window doesn't want to be visible, because in that
5352                        // case it explicitly doesn't want to be shown so we should
5353                        // not delay turning the screen on for it.
5354                        boolean vis = w.mViewVisibility == View.VISIBLE
5355                                && w.mPolicyVisibility;
5356                        haveKeyguard = !vis;
5357                    }
5358                    if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
5359                        return;
5360                    }
5361                    if (w.isDrawnLw()) {
5362                        if (w.mAttrs.type == TYPE_BOOT_PROGRESS) {
5363                            haveBootMsg = true;
5364                        } else if (w.mAttrs.type == TYPE_APPLICATION) {
5365                            haveApp = true;
5366                        } else if (w.mAttrs.type == TYPE_WALLPAPER) {
5367                            haveWallpaper = true;
5368                        } else if (w.mAttrs.type == TYPE_KEYGUARD) {
5369                            haveKeyguard = true;
5370                        }
5371                    }
5372                }
5373
5374                if (DEBUG_SCREEN_ON || DEBUG_BOOT) {
5375                    Slog.i(TAG, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages
5376                            + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp
5377                            + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled
5378                            + " haveKeyguard=" + haveKeyguard);
5379                }
5380
5381                // If we are turning on the screen to show the boot message,
5382                // don't do it until the boot message is actually displayed.
5383                if (!mSystemBooted && !haveBootMsg) {
5384                    return;
5385                }
5386
5387                // If we are turning on the screen after the boot is completed
5388                // normally, don't do so until we have the application and
5389                // wallpaper.
5390                if (mSystemBooted && ((!haveApp && !haveKeyguard) ||
5391                        (wallpaperEnabled && !haveWallpaper))) {
5392                    return;
5393                }
5394            }
5395
5396            mDisplayEnabled = true;
5397            if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG, "******************** ENABLING SCREEN!");
5398            if (false) {
5399                StringWriter sw = new StringWriter();
5400                PrintWriter pw = new FastPrintWriter(sw, false, 1024);
5401                this.dump(null, pw, null);
5402                pw.flush();
5403                Slog.i(TAG, sw.toString());
5404            }
5405            try {
5406                IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
5407                if (surfaceFlinger != null) {
5408                    //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
5409                    Parcel data = Parcel.obtain();
5410                    data.writeInterfaceToken("android.ui.ISurfaceComposer");
5411                    surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
5412                                            data, null, 0);
5413                    data.recycle();
5414                }
5415            } catch (RemoteException ex) {
5416                Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!");
5417            }
5418
5419            // Enable input dispatch.
5420            mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled);
5421        }
5422
5423        mPolicy.enableScreenAfterBoot();
5424
5425        // Make sure the last requested orientation has been applied.
5426        updateRotationUnchecked(false, false);
5427    }
5428
5429    public void showBootMessage(final CharSequence msg, final boolean always) {
5430        boolean first = false;
5431        synchronized(mWindowMap) {
5432            if (DEBUG_BOOT) {
5433                RuntimeException here = new RuntimeException("here");
5434                here.fillInStackTrace();
5435                Slog.i(TAG, "showBootMessage: msg=" + msg + " always=" + always
5436                        + " mAllowBootMessages=" + mAllowBootMessages
5437                        + " mShowingBootMessages=" + mShowingBootMessages
5438                        + " mSystemBooted=" + mSystemBooted, here);
5439            }
5440            if (!mAllowBootMessages) {
5441                return;
5442            }
5443            if (!mShowingBootMessages) {
5444                if (!always) {
5445                    return;
5446                }
5447                first = true;
5448            }
5449            if (mSystemBooted) {
5450                return;
5451            }
5452            mShowingBootMessages = true;
5453            mPolicy.showBootMessage(msg, always);
5454        }
5455        if (first) {
5456            performEnableScreen();
5457        }
5458    }
5459
5460    public void hideBootMessagesLocked() {
5461        if (DEBUG_BOOT) {
5462            RuntimeException here = new RuntimeException("here");
5463            here.fillInStackTrace();
5464            Slog.i(TAG, "hideBootMessagesLocked: mDisplayEnabled=" + mDisplayEnabled
5465                    + " mForceDisplayEnabled=" + mForceDisplayEnabled
5466                    + " mShowingBootMessages=" + mShowingBootMessages
5467                    + " mSystemBooted=" + mSystemBooted, here);
5468        }
5469        if (mShowingBootMessages) {
5470            mShowingBootMessages = false;
5471            mPolicy.hideBootMessages();
5472        }
5473    }
5474
5475    @Override
5476    public void setInTouchMode(boolean mode) {
5477        synchronized(mWindowMap) {
5478            mInTouchMode = mode;
5479        }
5480    }
5481
5482    // TODO: more accounting of which pid(s) turned it on, keep count,
5483    // only allow disables from pids which have count on, etc.
5484    @Override
5485    public void showStrictModeViolation(boolean on) {
5486        int pid = Binder.getCallingPid();
5487        mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, pid));
5488    }
5489
5490    private void showStrictModeViolation(int arg, int pid) {
5491        final boolean on = arg != 0;
5492        synchronized(mWindowMap) {
5493            // Ignoring requests to enable the red border from clients
5494            // which aren't on screen.  (e.g. Broadcast Receivers in
5495            // the background..)
5496            if (on) {
5497                boolean isVisible = false;
5498                final int numDisplays = mDisplayContents.size();
5499                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5500                    final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
5501                    final int numWindows = windows.size();
5502                    for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
5503                        final WindowState ws = windows.get(winNdx);
5504                        if (ws.mSession.mPid == pid && ws.isVisibleLw()) {
5505                            isVisible = true;
5506                            break;
5507                        }
5508                    }
5509                }
5510                if (!isVisible) {
5511                    return;
5512                }
5513            }
5514
5515            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5516                    ">>> OPEN TRANSACTION showStrictModeViolation");
5517            SurfaceControl.openTransaction();
5518            try {
5519                // TODO(multi-display): support multiple displays
5520                if (mStrictModeFlash == null) {
5521                    mStrictModeFlash = new StrictModeFlash(
5522                            getDefaultDisplayContentLocked().getDisplay(), mFxSession);
5523                }
5524                mStrictModeFlash.setVisibility(on);
5525            } finally {
5526                SurfaceControl.closeTransaction();
5527                if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5528                        "<<< CLOSE TRANSACTION showStrictModeViolation");
5529            }
5530        }
5531    }
5532
5533    @Override
5534    public void setStrictModeVisualIndicatorPreference(String value) {
5535        SystemProperties.set(StrictMode.VISUAL_PROPERTY, value);
5536    }
5537
5538    /**
5539     * Takes a snapshot of the screen.  In landscape mode this grabs the whole screen.
5540     * In portrait mode, it grabs the upper region of the screen based on the vertical dimension
5541     * of the target image.
5542     *
5543     * @param displayId the Display to take a screenshot of.
5544     * @param width the width of the target bitmap
5545     * @param height the height of the target bitmap
5546     * @param force565 if true the returned bitmap will be RGB_565, otherwise it
5547     *                 will be the same config as the surface
5548     */
5549    @Override
5550    public Bitmap screenshotApplications(IBinder appToken, int displayId, int width,
5551            int height, boolean force565) {
5552        if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
5553                "screenshotApplications()")) {
5554            throw new SecurityException("Requires READ_FRAME_BUFFER permission");
5555        }
5556
5557        Bitmap rawss = null;
5558
5559        int maxLayer = 0;
5560        final Rect frame = new Rect();
5561
5562        float scale = 0;
5563        int dw, dh;
5564        int rot = Surface.ROTATION_0;
5565
5566        boolean screenshotReady;
5567        int minLayer;
5568        if (appToken == null) {
5569            screenshotReady = true;
5570            minLayer = 0;
5571        } else {
5572            screenshotReady = false;
5573            minLayer = Integer.MAX_VALUE;
5574        }
5575
5576        int retryCount = 0;
5577        WindowState appWin = null;
5578
5579        do {
5580            if (retryCount++ > 0) {
5581                try {
5582                    Thread.sleep(100);
5583                } catch (InterruptedException e) {
5584                }
5585            }
5586            synchronized(mWindowMap) {
5587                final DisplayContent displayContent = getDisplayContentLocked(displayId);
5588                if (displayContent == null) {
5589                    return null;
5590                }
5591                final DisplayInfo displayInfo = displayContent.getDisplayInfo();
5592                dw = displayInfo.logicalWidth;
5593                dh = displayInfo.logicalHeight;
5594
5595                int aboveAppLayer = mPolicy.windowTypeToLayerLw(TYPE_APPLICATION)
5596                        * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
5597                aboveAppLayer += TYPE_LAYER_MULTIPLIER;
5598
5599                boolean isImeTarget = mInputMethodTarget != null
5600                        && mInputMethodTarget.mAppToken != null
5601                        && mInputMethodTarget.mAppToken.appToken != null
5602                        && mInputMethodTarget.mAppToken.appToken.asBinder() == appToken;
5603
5604                // Figure out the part of the screen that is actually the app.
5605                boolean including = false;
5606                appWin = null;
5607                final WindowList windows = displayContent.getWindowList();
5608                final Rect stackBounds = new Rect();
5609                for (int i = windows.size() - 1; i >= 0; i--) {
5610                    WindowState ws = windows.get(i);
5611                    if (!ws.mHasSurface) {
5612                        continue;
5613                    }
5614                    if (ws.mLayer >= aboveAppLayer) {
5615                        continue;
5616                    }
5617                    // When we will skip windows: when we are not including
5618                    // ones behind a window we didn't skip, and we are actually
5619                    // taking a screenshot of a specific app.
5620                    if (!including && appToken != null) {
5621                        // Also, we can possibly skip this window if it is not
5622                        // an IME target or the application for the screenshot
5623                        // is not the current IME target.
5624                        if (!ws.mIsImWindow || !isImeTarget) {
5625                            // And finally, this window is of no interest if it
5626                            // is not associated with the screenshot app.
5627                            if (ws.mAppToken == null || ws.mAppToken.token != appToken) {
5628                                continue;
5629                            }
5630                            appWin = ws;
5631                            ws.getStackBounds(stackBounds);
5632                        }
5633                    }
5634
5635                    // We keep on including windows until we go past a full-screen
5636                    // window.
5637                    including = !ws.mIsImWindow && !ws.isFullscreen(dw, dh);
5638
5639                    final WindowStateAnimator winAnim = ws.mWinAnimator;
5640                    if (maxLayer < winAnim.mSurfaceLayer) {
5641                        maxLayer = winAnim.mSurfaceLayer;
5642                    }
5643                    if (minLayer > winAnim.mSurfaceLayer) {
5644                        minLayer = winAnim.mSurfaceLayer;
5645                    }
5646
5647                    // Don't include wallpaper in bounds calculation
5648                    if (!ws.mIsWallpaper) {
5649                        final Rect wf = ws.mFrame;
5650                        final Rect cr = ws.mContentInsets;
5651                        int left = wf.left + cr.left;
5652                        int top = wf.top + cr.top;
5653                        int right = wf.right - cr.right;
5654                        int bottom = wf.bottom - cr.bottom;
5655                        frame.union(left, top, right, bottom);
5656                        frame.intersect(stackBounds);
5657                    }
5658
5659                    if (ws.mAppToken != null && ws.mAppToken.token == appToken &&
5660                            ws.isDisplayedLw()) {
5661                        screenshotReady = true;
5662                    }
5663                }
5664
5665                if (appToken != null && appWin == null) {
5666                    // Can't find a window to snapshot.
5667                    if (DEBUG_SCREENSHOT) Slog.i(TAG,
5668                            "Screenshot: Couldn't find a surface matching " + appToken);
5669                    return null;
5670                }
5671                if (!screenshotReady) {
5672                    // Delay and hope that window gets drawn.
5673                    if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot: No image ready for " + appToken
5674                            + ", " + appWin + " drawState=" + appWin.mWinAnimator.mDrawState);
5675                    continue;
5676                }
5677
5678                // Constrain frame to the screen size.
5679                frame.intersect(0, 0, dw, dh);
5680
5681                if (frame.isEmpty() || maxLayer == 0) {
5682                    if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken
5683                            + ": returning null frame=" + frame.toShortString() + " maxLayer="
5684                            + maxLayer);
5685                    return null;
5686                }
5687
5688                // The screenshot API does not apply the current screen rotation.
5689                rot = getDefaultDisplayContentLocked().getDisplay().getRotation();
5690                int fw = frame.width();
5691                int fh = frame.height();
5692
5693                // Constrain thumbnail to smaller of screen width or height. Assumes aspect
5694                // of thumbnail is the same as the screen (in landscape) or square.
5695                scale = Math.max(width / (float) fw, height / (float) fh);
5696                /*
5697                float targetWidthScale = width / (float) fw;
5698                float targetHeightScale = height / (float) fh;
5699                if (fw <= fh) {
5700                    scale = targetWidthScale;
5701                    // If aspect of thumbnail is the same as the screen (in landscape),
5702                    // select the slightly larger value so we fill the entire bitmap
5703                    if (targetHeightScale > scale && (int) (targetHeightScale * fw) == width) {
5704                        scale = targetHeightScale;
5705                    }
5706                } else {
5707                    scale = targetHeightScale;
5708                    // If aspect of thumbnail is the same as the screen (in landscape),
5709                    // select the slightly larger value so we fill the entire bitmap
5710                    if (targetWidthScale > scale && (int) (targetWidthScale * fh) == height) {
5711                        scale = targetWidthScale;
5712                    }
5713                }
5714                */
5715
5716                // The screen shot will contain the entire screen.
5717                dw = (int)(dw*scale);
5718                dh = (int)(dh*scale);
5719                if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
5720                    int tmp = dw;
5721                    dw = dh;
5722                    dh = tmp;
5723                    rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90;
5724                }
5725                if (DEBUG_SCREENSHOT) {
5726                    Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to "
5727                            + maxLayer + " appToken=" + appToken);
5728                    for (int i = 0; i < windows.size(); i++) {
5729                        WindowState win = windows.get(i);
5730                        Slog.i(TAG, win + ": " + win.mLayer
5731                                + " animLayer=" + win.mWinAnimator.mAnimLayer
5732                                + " surfaceLayer=" + win.mWinAnimator.mSurfaceLayer);
5733                    }
5734                }
5735                rawss = SurfaceControl.screenshot(dw, dh, minLayer, maxLayer);
5736            }
5737        } while (!screenshotReady && retryCount <= MAX_SCREENSHOT_RETRIES);
5738        if (retryCount > MAX_SCREENSHOT_RETRIES)  Slog.i(TAG, "Screenshot max retries " +
5739                retryCount + " of " + appToken + " appWin=" + (appWin == null ?
5740                        "null" : (appWin + " drawState=" + appWin.mWinAnimator.mDrawState)));
5741
5742        if (rawss == null) {
5743            Slog.w(TAG, "Screenshot failure taking screenshot for (" + dw + "x" + dh
5744                    + ") to layer " + maxLayer);
5745            return null;
5746        }
5747
5748        Bitmap bm = Bitmap.createBitmap(width, height, force565 ? Config.RGB_565 : rawss.getConfig());
5749        frame.scale(scale);
5750        Matrix matrix = new Matrix();
5751        ScreenRotationAnimation.createRotationMatrix(rot, dw, dh, matrix);
5752        // TODO: Test for RTL vs. LTR and use frame.right-width instead of -frame.left
5753        matrix.postTranslate(-FloatMath.ceil(frame.left), -FloatMath.ceil(frame.top));
5754        Canvas canvas = new Canvas(bm);
5755        canvas.drawColor(0xFF000000);
5756        canvas.drawBitmap(rawss, matrix, null);
5757        canvas.setBitmap(null);
5758
5759        if (DEBUG_SCREENSHOT) {
5760            // TEST IF IT's ALL BLACK
5761            int[] buffer = new int[bm.getWidth() * bm.getHeight()];
5762            bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight());
5763            boolean allBlack = true;
5764            final int firstColor = buffer[0];
5765            for (int i = 0; i < buffer.length; i++) {
5766                if (buffer[i] != firstColor) {
5767                    allBlack = false;
5768                    break;
5769                }
5770            }
5771            if (allBlack) {
5772                Slog.i(TAG, "Screenshot " + appWin + " was monochrome(" +
5773                        Integer.toHexString(firstColor) + ")! mSurfaceLayer=" +
5774                        (appWin != null ? appWin.mWinAnimator.mSurfaceLayer : "null") +
5775                        " minLayer=" + minLayer + " maxLayer=" + maxLayer);
5776            }
5777        }
5778
5779        rawss.recycle();
5780        return bm;
5781    }
5782
5783    /**
5784     * Freeze rotation changes.  (Enable "rotation lock".)
5785     * Persists across reboots.
5786     * @param rotation The desired rotation to freeze to, or -1 to use the
5787     * current rotation.
5788     */
5789    @Override
5790    public void freezeRotation(int rotation) {
5791        if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
5792                "freezeRotation()")) {
5793            throw new SecurityException("Requires SET_ORIENTATION permission");
5794        }
5795        if (rotation < -1 || rotation > Surface.ROTATION_270) {
5796            throw new IllegalArgumentException("Rotation argument must be -1 or a valid "
5797                    + "rotation constant.");
5798        }
5799
5800        if (DEBUG_ORIENTATION) Slog.v(TAG, "freezeRotation: mRotation=" + mRotation);
5801
5802        long origId = Binder.clearCallingIdentity();
5803        try {
5804            mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED,
5805                    rotation == -1 ? mRotation : rotation);
5806        } finally {
5807            Binder.restoreCallingIdentity(origId);
5808        }
5809
5810        updateRotationUnchecked(false, false);
5811    }
5812
5813    /**
5814     * Thaw rotation changes.  (Disable "rotation lock".)
5815     * Persists across reboots.
5816     */
5817    @Override
5818    public void thawRotation() {
5819        if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
5820                "thawRotation()")) {
5821            throw new SecurityException("Requires SET_ORIENTATION permission");
5822        }
5823
5824        if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation);
5825
5826        long origId = Binder.clearCallingIdentity();
5827        try {
5828            mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE,
5829                    777); // rot not used
5830        } finally {
5831            Binder.restoreCallingIdentity(origId);
5832        }
5833
5834        updateRotationUnchecked(false, false);
5835    }
5836
5837    /**
5838     * Recalculate the current rotation.
5839     *
5840     * Called by the window manager policy whenever the state of the system changes
5841     * such that the current rotation might need to be updated, such as when the
5842     * device is docked or rotated into a new posture.
5843     */
5844    @Override
5845    public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
5846        updateRotationUnchecked(alwaysSendConfiguration, forceRelayout);
5847    }
5848
5849    /**
5850     * Temporarily pauses rotation changes until resumed.
5851     *
5852     * This can be used to prevent rotation changes from occurring while the user is
5853     * performing certain operations, such as drag and drop.
5854     *
5855     * This call nests and must be matched by an equal number of calls to
5856     * {@link #resumeRotationLocked}.
5857     */
5858    void pauseRotationLocked() {
5859        mDeferredRotationPauseCount += 1;
5860    }
5861
5862    /**
5863     * Resumes normal rotation changes after being paused.
5864     */
5865    void resumeRotationLocked() {
5866        if (mDeferredRotationPauseCount > 0) {
5867            mDeferredRotationPauseCount -= 1;
5868            if (mDeferredRotationPauseCount == 0) {
5869                boolean changed = updateRotationUncheckedLocked(false);
5870                if (changed) {
5871                    mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
5872                }
5873            }
5874        }
5875    }
5876
5877    public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) {
5878        if(DEBUG_ORIENTATION) Slog.v(TAG, "updateRotationUnchecked("
5879                   + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")");
5880
5881        long origId = Binder.clearCallingIdentity();
5882        boolean changed;
5883        synchronized(mWindowMap) {
5884            changed = updateRotationUncheckedLocked(false);
5885            if (!changed || forceRelayout) {
5886                getDefaultDisplayContentLocked().layoutNeeded = true;
5887                performLayoutAndPlaceSurfacesLocked();
5888            }
5889        }
5890
5891        if (changed || alwaysSendConfiguration) {
5892            sendNewConfiguration();
5893        }
5894
5895        Binder.restoreCallingIdentity(origId);
5896    }
5897
5898    // TODO(multidisplay): Rotate any display?
5899    /**
5900     * Updates the current rotation.
5901     *
5902     * Returns true if the rotation has been changed.  In this case YOU
5903     * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN.
5904     */
5905    public boolean updateRotationUncheckedLocked(boolean inTransaction) {
5906        if (mDeferredRotationPauseCount > 0) {
5907            // Rotation updates have been paused temporarily.  Defer the update until
5908            // updates have been resumed.
5909            if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, rotation is paused.");
5910            return false;
5911        }
5912
5913        ScreenRotationAnimation screenRotationAnimation =
5914                mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
5915        if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
5916            // Rotation updates cannot be performed while the previous rotation change
5917            // animation is still in progress.  Skip this update.  We will try updating
5918            // again after the animation is finished and the display is unfrozen.
5919            if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, animation in progress.");
5920            return false;
5921        }
5922
5923        if (!mDisplayEnabled) {
5924            // No point choosing a rotation if the display is not enabled.
5925            if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, display is not enabled.");
5926            return false;
5927        }
5928
5929        // TODO: Implement forced rotation changes.
5930        //       Set mAltOrientation to indicate that the application is receiving
5931        //       an orientation that has different metrics than it expected.
5932        //       eg. Portrait instead of Landscape.
5933
5934        int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation);
5935        boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw(
5936                mForcedAppOrientation, rotation);
5937
5938        if (DEBUG_ORIENTATION) {
5939            Slog.v(TAG, "Application requested orientation "
5940                    + mForcedAppOrientation + ", got rotation " + rotation
5941                    + " which has " + (altOrientation ? "incompatible" : "compatible")
5942                    + " metrics");
5943        }
5944
5945        if (mRotation == rotation && mAltOrientation == altOrientation) {
5946            // No change.
5947            return false;
5948        }
5949
5950        if (DEBUG_ORIENTATION) {
5951            Slog.v(TAG,
5952                "Rotation changed to " + rotation + (altOrientation ? " (alt)" : "")
5953                + " from " + mRotation + (mAltOrientation ? " (alt)" : "")
5954                + ", forceApp=" + mForcedAppOrientation);
5955        }
5956
5957        mRotation = rotation;
5958        mAltOrientation = altOrientation;
5959        mPolicy.setRotationLw(mRotation);
5960
5961        mWindowsFreezingScreen = true;
5962        mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
5963        mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION);
5964        mWaitingForConfig = true;
5965        final DisplayContent displayContent = getDefaultDisplayContentLocked();
5966        displayContent.layoutNeeded = true;
5967        final int[] anim = new int[2];
5968        if (displayContent.isDimming()) {
5969            anim[0] = anim[1] = 0;
5970        } else {
5971            mPolicy.selectRotationAnimationLw(anim);
5972        }
5973        startFreezingDisplayLocked(inTransaction, anim[0], anim[1]);
5974        // startFreezingDisplayLocked can reset the ScreenRotationAnimation.
5975        screenRotationAnimation =
5976                mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
5977
5978        // We need to update our screen size information to match the new
5979        // rotation.  Note that this is redundant with the later call to
5980        // sendNewConfiguration() that must be called after this function
5981        // returns...  however we need to do the screen size part of that
5982        // before then so we have the correct size to use when initializing
5983        // the rotation animation for the new rotation.
5984        computeScreenConfigurationLocked(null);
5985
5986        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
5987        if (!inTransaction) {
5988            if (SHOW_TRANSACTIONS) {
5989                Slog.i(TAG, ">>> OPEN TRANSACTION setRotationUnchecked");
5990            }
5991            SurfaceControl.openTransaction();
5992        }
5993        try {
5994            // NOTE: We disable the rotation in the emulator because
5995            //       it doesn't support hardware OpenGL emulation yet.
5996            if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
5997                    && screenRotationAnimation.hasScreenshot()) {
5998                if (screenRotationAnimation.setRotationInTransaction(
5999                        rotation, mFxSession,
6000                        MAX_ANIMATION_DURATION, mTransitionAnimationScale,
6001                        displayInfo.logicalWidth, displayInfo.logicalHeight)) {
6002                    scheduleAnimationLocked();
6003                }
6004            }
6005
6006            mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
6007        } finally {
6008            if (!inTransaction) {
6009                SurfaceControl.closeTransaction();
6010                if (SHOW_LIGHT_TRANSACTIONS) {
6011                    Slog.i(TAG, "<<< CLOSE TRANSACTION setRotationUnchecked");
6012                }
6013            }
6014        }
6015
6016        final WindowList windows = displayContent.getWindowList();
6017        for (int i = windows.size() - 1; i >= 0; i--) {
6018            WindowState w = windows.get(i);
6019            if (w.mHasSurface) {
6020                if (DEBUG_ORIENTATION) Slog.v(TAG, "Set mOrientationChanging of " + w);
6021                w.mOrientationChanging = true;
6022                mInnerFields.mOrientationChangeComplete = false;
6023            }
6024            w.mLastFreezeDuration = 0;
6025        }
6026
6027        for (int i=mRotationWatchers.size()-1; i>=0; i--) {
6028            try {
6029                mRotationWatchers.get(i).onRotationChanged(rotation);
6030            } catch (RemoteException e) {
6031            }
6032        }
6033
6034        //TODO (multidisplay): Magnification is supported only for the default display.
6035        if (mDisplayMagnifier != null
6036                && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) {
6037            mDisplayMagnifier.onRotationChangedLocked(getDefaultDisplayContentLocked(), rotation);
6038        }
6039
6040        return true;
6041    }
6042
6043    @Override
6044    public int getRotation() {
6045        return mRotation;
6046    }
6047
6048    @Override
6049    public boolean isRotationFrozen() {
6050        return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED;
6051    }
6052
6053    @Override
6054    public int watchRotation(IRotationWatcher watcher) {
6055        final IBinder watcherBinder = watcher.asBinder();
6056        IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
6057            @Override
6058            public void binderDied() {
6059                synchronized (mWindowMap) {
6060                    for (int i=0; i<mRotationWatchers.size(); i++) {
6061                        if (watcherBinder == mRotationWatchers.get(i).asBinder()) {
6062                            IRotationWatcher removed = mRotationWatchers.remove(i);
6063                            if (removed != null) {
6064                                removed.asBinder().unlinkToDeath(this, 0);
6065                            }
6066                            i--;
6067                        }
6068                    }
6069                }
6070            }
6071        };
6072
6073        synchronized (mWindowMap) {
6074            try {
6075                watcher.asBinder().linkToDeath(dr, 0);
6076                mRotationWatchers.add(watcher);
6077            } catch (RemoteException e) {
6078                // Client died, no cleanup needed.
6079            }
6080
6081            return mRotation;
6082        }
6083    }
6084
6085    @Override
6086    public void removeRotationWatcher(IRotationWatcher watcher) {
6087        final IBinder watcherBinder = watcher.asBinder();
6088        synchronized (mWindowMap) {
6089            for (int i=0; i<mRotationWatchers.size(); i++) {
6090                if (watcherBinder == mRotationWatchers.get(i).asBinder()) {
6091                    mRotationWatchers.remove(i);
6092                    i--;
6093                }
6094            }
6095        }
6096    }
6097
6098    /**
6099     * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact
6100     * theme attribute) on devices that feature a physical options menu key attempt to position
6101     * their menu panel window along the edge of the screen nearest the physical menu key.
6102     * This lowers the travel distance between invoking the menu panel and selecting
6103     * a menu option.
6104     *
6105     * This method helps control where that menu is placed. Its current implementation makes
6106     * assumptions about the menu key and its relationship to the screen based on whether
6107     * the device's natural orientation is portrait (width < height) or landscape.
6108     *
6109     * The menu key is assumed to be located along the bottom edge of natural-portrait
6110     * devices and along the right edge of natural-landscape devices. If these assumptions
6111     * do not hold for the target device, this method should be changed to reflect that.
6112     *
6113     * @return A {@link Gravity} value for placing the options menu window
6114     */
6115    @Override
6116    public int getPreferredOptionsPanelGravity() {
6117        synchronized (mWindowMap) {
6118            final int rotation = getRotation();
6119
6120            // TODO(multidisplay): Assume that such devices physical keys are on the main screen.
6121            final DisplayContent displayContent = getDefaultDisplayContentLocked();
6122            if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) {
6123                // On devices with a natural orientation of portrait
6124                switch (rotation) {
6125                    default:
6126                    case Surface.ROTATION_0:
6127                        return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6128                    case Surface.ROTATION_90:
6129                        return Gravity.RIGHT | Gravity.BOTTOM;
6130                    case Surface.ROTATION_180:
6131                        return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6132                    case Surface.ROTATION_270:
6133                        return Gravity.START | Gravity.BOTTOM;
6134                }
6135            }
6136
6137            // On devices with a natural orientation of landscape
6138            switch (rotation) {
6139                default:
6140                case Surface.ROTATION_0:
6141                    return Gravity.RIGHT | Gravity.BOTTOM;
6142                case Surface.ROTATION_90:
6143                    return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6144                case Surface.ROTATION_180:
6145                    return Gravity.START | Gravity.BOTTOM;
6146                case Surface.ROTATION_270:
6147                    return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6148            }
6149        }
6150    }
6151
6152    /**
6153     * Starts the view server on the specified port.
6154     *
6155     * @param port The port to listener to.
6156     *
6157     * @return True if the server was successfully started, false otherwise.
6158     *
6159     * @see com.android.server.wm.ViewServer
6160     * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT
6161     */
6162    @Override
6163    public boolean startViewServer(int port) {
6164        if (isSystemSecure()) {
6165            return false;
6166        }
6167
6168        if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) {
6169            return false;
6170        }
6171
6172        if (port < 1024) {
6173            return false;
6174        }
6175
6176        if (mViewServer != null) {
6177            if (!mViewServer.isRunning()) {
6178                try {
6179                    return mViewServer.start();
6180                } catch (IOException e) {
6181                    Slog.w(TAG, "View server did not start");
6182                }
6183            }
6184            return false;
6185        }
6186
6187        try {
6188            mViewServer = new ViewServer(this, port);
6189            return mViewServer.start();
6190        } catch (IOException e) {
6191            Slog.w(TAG, "View server did not start");
6192        }
6193        return false;
6194    }
6195
6196    private boolean isSystemSecure() {
6197        return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) &&
6198                "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
6199    }
6200
6201    /**
6202     * Stops the view server if it exists.
6203     *
6204     * @return True if the server stopped, false if it wasn't started or
6205     *         couldn't be stopped.
6206     *
6207     * @see com.android.server.wm.ViewServer
6208     */
6209    @Override
6210    public boolean stopViewServer() {
6211        if (isSystemSecure()) {
6212            return false;
6213        }
6214
6215        if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) {
6216            return false;
6217        }
6218
6219        if (mViewServer != null) {
6220            return mViewServer.stop();
6221        }
6222        return false;
6223    }
6224
6225    /**
6226     * Indicates whether the view server is running.
6227     *
6228     * @return True if the server is running, false otherwise.
6229     *
6230     * @see com.android.server.wm.ViewServer
6231     */
6232    @Override
6233    public boolean isViewServerRunning() {
6234        if (isSystemSecure()) {
6235            return false;
6236        }
6237
6238        if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) {
6239            return false;
6240        }
6241
6242        return mViewServer != null && mViewServer.isRunning();
6243    }
6244
6245    /**
6246     * Lists all availble windows in the system. The listing is written in the
6247     * specified Socket's output stream with the following syntax:
6248     * windowHashCodeInHexadecimal windowName
6249     * Each line of the ouput represents a different window.
6250     *
6251     * @param client The remote client to send the listing to.
6252     * @return False if an error occured, true otherwise.
6253     */
6254    boolean viewServerListWindows(Socket client) {
6255        if (isSystemSecure()) {
6256            return false;
6257        }
6258
6259        boolean result = true;
6260
6261        WindowList windows = new WindowList();
6262        synchronized (mWindowMap) {
6263            //noinspection unchecked
6264            final int numDisplays = mDisplayContents.size();
6265            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
6266                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
6267                windows.addAll(displayContent.getWindowList());
6268            }
6269        }
6270
6271        BufferedWriter out = null;
6272
6273        // Any uncaught exception will crash the system process
6274        try {
6275            OutputStream clientStream = client.getOutputStream();
6276            out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
6277
6278            final int count = windows.size();
6279            for (int i = 0; i < count; i++) {
6280                final WindowState w = windows.get(i);
6281                out.write(Integer.toHexString(System.identityHashCode(w)));
6282                out.write(' ');
6283                out.append(w.mAttrs.getTitle());
6284                out.write('\n');
6285            }
6286
6287            out.write("DONE.\n");
6288            out.flush();
6289        } catch (Exception e) {
6290            result = false;
6291        } finally {
6292            if (out != null) {
6293                try {
6294                    out.close();
6295                } catch (IOException e) {
6296                    result = false;
6297                }
6298            }
6299        }
6300
6301        return result;
6302    }
6303
6304    // TODO(multidisplay): Extend to multiple displays.
6305    /**
6306     * Returns the focused window in the following format:
6307     * windowHashCodeInHexadecimal windowName
6308     *
6309     * @param client The remote client to send the listing to.
6310     * @return False if an error occurred, true otherwise.
6311     */
6312    boolean viewServerGetFocusedWindow(Socket client) {
6313        if (isSystemSecure()) {
6314            return false;
6315        }
6316
6317        boolean result = true;
6318
6319        WindowState focusedWindow = getFocusedWindow();
6320
6321        BufferedWriter out = null;
6322
6323        // Any uncaught exception will crash the system process
6324        try {
6325            OutputStream clientStream = client.getOutputStream();
6326            out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
6327
6328            if(focusedWindow != null) {
6329                out.write(Integer.toHexString(System.identityHashCode(focusedWindow)));
6330                out.write(' ');
6331                out.append(focusedWindow.mAttrs.getTitle());
6332            }
6333            out.write('\n');
6334            out.flush();
6335        } catch (Exception e) {
6336            result = false;
6337        } finally {
6338            if (out != null) {
6339                try {
6340                    out.close();
6341                } catch (IOException e) {
6342                    result = false;
6343                }
6344            }
6345        }
6346
6347        return result;
6348    }
6349
6350    /**
6351     * Sends a command to a target window. The result of the command, if any, will be
6352     * written in the output stream of the specified socket.
6353     *
6354     * The parameters must follow this syntax:
6355     * windowHashcode extra
6356     *
6357     * Where XX is the length in characeters of the windowTitle.
6358     *
6359     * The first parameter is the target window. The window with the specified hashcode
6360     * will be the target. If no target can be found, nothing happens. The extra parameters
6361     * will be delivered to the target window and as parameters to the command itself.
6362     *
6363     * @param client The remote client to sent the result, if any, to.
6364     * @param command The command to execute.
6365     * @param parameters The command parameters.
6366     *
6367     * @return True if the command was successfully delivered, false otherwise. This does
6368     *         not indicate whether the command itself was successful.
6369     */
6370    boolean viewServerWindowCommand(Socket client, String command, String parameters) {
6371        if (isSystemSecure()) {
6372            return false;
6373        }
6374
6375        boolean success = true;
6376        Parcel data = null;
6377        Parcel reply = null;
6378
6379        BufferedWriter out = null;
6380
6381        // Any uncaught exception will crash the system process
6382        try {
6383            // Find the hashcode of the window
6384            int index = parameters.indexOf(' ');
6385            if (index == -1) {
6386                index = parameters.length();
6387            }
6388            final String code = parameters.substring(0, index);
6389            int hashCode = (int) Long.parseLong(code, 16);
6390
6391            // Extract the command's parameter after the window description
6392            if (index < parameters.length()) {
6393                parameters = parameters.substring(index + 1);
6394            } else {
6395                parameters = "";
6396            }
6397
6398            final WindowState window = findWindow(hashCode);
6399            if (window == null) {
6400                return false;
6401            }
6402
6403            data = Parcel.obtain();
6404            data.writeInterfaceToken("android.view.IWindow");
6405            data.writeString(command);
6406            data.writeString(parameters);
6407            data.writeInt(1);
6408            ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0);
6409
6410            reply = Parcel.obtain();
6411
6412            final IBinder binder = window.mClient.asBinder();
6413            // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER
6414            binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
6415
6416            reply.readException();
6417
6418            if (!client.isOutputShutdown()) {
6419                out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
6420                out.write("DONE\n");
6421                out.flush();
6422            }
6423
6424        } catch (Exception e) {
6425            Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e);
6426            success = false;
6427        } finally {
6428            if (data != null) {
6429                data.recycle();
6430            }
6431            if (reply != null) {
6432                reply.recycle();
6433            }
6434            if (out != null) {
6435                try {
6436                    out.close();
6437                } catch (IOException e) {
6438
6439                }
6440            }
6441        }
6442
6443        return success;
6444    }
6445
6446    public void addWindowChangeListener(WindowChangeListener listener) {
6447        synchronized(mWindowMap) {
6448            mWindowChangeListeners.add(listener);
6449        }
6450    }
6451
6452    public void removeWindowChangeListener(WindowChangeListener listener) {
6453        synchronized(mWindowMap) {
6454            mWindowChangeListeners.remove(listener);
6455        }
6456    }
6457
6458    private void notifyWindowsChanged() {
6459        WindowChangeListener[] windowChangeListeners;
6460        synchronized(mWindowMap) {
6461            if(mWindowChangeListeners.isEmpty()) {
6462                return;
6463            }
6464            windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
6465            windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
6466        }
6467        int N = windowChangeListeners.length;
6468        for(int i = 0; i < N; i++) {
6469            windowChangeListeners[i].windowsChanged();
6470        }
6471    }
6472
6473    private void notifyFocusChanged() {
6474        WindowChangeListener[] windowChangeListeners;
6475        synchronized(mWindowMap) {
6476            if(mWindowChangeListeners.isEmpty()) {
6477                return;
6478            }
6479            windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
6480            windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
6481        }
6482        int N = windowChangeListeners.length;
6483        for(int i = 0; i < N; i++) {
6484            windowChangeListeners[i].focusChanged();
6485        }
6486    }
6487
6488    private WindowState findWindow(int hashCode) {
6489        if (hashCode == -1) {
6490            // TODO(multidisplay): Extend to multiple displays.
6491            return getFocusedWindow();
6492        }
6493
6494        synchronized (mWindowMap) {
6495            final int numDisplays = mDisplayContents.size();
6496            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
6497                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
6498                final int numWindows = windows.size();
6499                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
6500                    final WindowState w = windows.get(winNdx);
6501                    if (System.identityHashCode(w) == hashCode) {
6502                        return w;
6503                    }
6504                }
6505            }
6506        }
6507
6508        return null;
6509    }
6510
6511    /*
6512     * Instruct the Activity Manager to fetch the current configuration and broadcast
6513     * that to config-changed listeners if appropriate.
6514     */
6515    void sendNewConfiguration() {
6516        try {
6517            mActivityManager.updateConfiguration(null);
6518        } catch (RemoteException e) {
6519        }
6520    }
6521
6522    public Configuration computeNewConfiguration() {
6523        synchronized (mWindowMap) {
6524            Configuration config = computeNewConfigurationLocked();
6525            if (config == null && mWaitingForConfig) {
6526                // Nothing changed but we are waiting for something... stop that!
6527                mWaitingForConfig = false;
6528                mLastFinishedFreezeSource = "new-config";
6529                performLayoutAndPlaceSurfacesLocked();
6530            }
6531            return config;
6532        }
6533    }
6534
6535    Configuration computeNewConfigurationLocked() {
6536        Configuration config = new Configuration();
6537        config.fontScale = 0;
6538        if (!computeScreenConfigurationLocked(config)) {
6539            return null;
6540        }
6541        return config;
6542    }
6543
6544    private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int dw, int dh) {
6545        // TODO: Multidisplay: for now only use with default display.
6546        final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation);
6547        if (width < displayInfo.smallestNominalAppWidth) {
6548            displayInfo.smallestNominalAppWidth = width;
6549        }
6550        if (width > displayInfo.largestNominalAppWidth) {
6551            displayInfo.largestNominalAppWidth = width;
6552        }
6553        final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation);
6554        if (height < displayInfo.smallestNominalAppHeight) {
6555            displayInfo.smallestNominalAppHeight = height;
6556        }
6557        if (height > displayInfo.largestNominalAppHeight) {
6558            displayInfo.largestNominalAppHeight = height;
6559        }
6560    }
6561
6562    private int reduceConfigLayout(int curLayout, int rotation, float density,
6563            int dw, int dh) {
6564        // TODO: Multidisplay: for now only use with default display.
6565        // Get the app screen size at this rotation.
6566        int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation);
6567        int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation);
6568
6569        // Compute the screen layout size class for this rotation.
6570        int longSize = w;
6571        int shortSize = h;
6572        if (longSize < shortSize) {
6573            int tmp = longSize;
6574            longSize = shortSize;
6575            shortSize = tmp;
6576        }
6577        longSize = (int)(longSize/density);
6578        shortSize = (int)(shortSize/density);
6579        return Configuration.reduceScreenLayout(curLayout, longSize, shortSize);
6580    }
6581
6582    private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated,
6583                  int dw, int dh, float density, Configuration outConfig) {
6584        // TODO: Multidisplay: for now only use with default display.
6585
6586        // We need to determine the smallest width that will occur under normal
6587        // operation.  To this, start with the base screen size and compute the
6588        // width under the different possible rotations.  We need to un-rotate
6589        // the current screen dimensions before doing this.
6590        int unrotDw, unrotDh;
6591        if (rotated) {
6592            unrotDw = dh;
6593            unrotDh = dw;
6594        } else {
6595            unrotDw = dw;
6596            unrotDh = dh;
6597        }
6598        displayInfo.smallestNominalAppWidth = 1<<30;
6599        displayInfo.smallestNominalAppHeight = 1<<30;
6600        displayInfo.largestNominalAppWidth = 0;
6601        displayInfo.largestNominalAppHeight = 0;
6602        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, unrotDw, unrotDh);
6603        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, unrotDh, unrotDw);
6604        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, unrotDw, unrotDh);
6605        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, unrotDh, unrotDw);
6606        int sl = Configuration.resetScreenLayout(outConfig.screenLayout);
6607        sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh);
6608        sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw);
6609        sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh);
6610        sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw);
6611        outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density);
6612        outConfig.screenLayout = sl;
6613    }
6614
6615    private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm,
6616            int dw, int dh) {
6617        // TODO: Multidisplay: for now only use with default display.
6618        dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation);
6619        dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation);
6620        float scale = CompatibilityInfo.computeCompatibleScaling(dm, null);
6621        int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f);
6622        if (curSize == 0 || size < curSize) {
6623            curSize = size;
6624        }
6625        return curSize;
6626    }
6627
6628    private int computeCompatSmallestWidth(boolean rotated, DisplayMetrics dm, int dw, int dh) {
6629        // TODO: Multidisplay: for now only use with default display.
6630        mTmpDisplayMetrics.setTo(dm);
6631        final DisplayMetrics tmpDm = mTmpDisplayMetrics;
6632        final int unrotDw, unrotDh;
6633        if (rotated) {
6634            unrotDw = dh;
6635            unrotDh = dw;
6636        } else {
6637            unrotDw = dw;
6638            unrotDh = dh;
6639        }
6640        int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, tmpDm, unrotDw, unrotDh);
6641        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, tmpDm, unrotDh, unrotDw);
6642        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, tmpDm, unrotDw, unrotDh);
6643        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, tmpDm, unrotDh, unrotDw);
6644        return sw;
6645    }
6646
6647    boolean computeScreenConfigurationLocked(Configuration config) {
6648        if (!mDisplayReady) {
6649            return false;
6650        }
6651
6652        // TODO(multidisplay): For now, apply Configuration to main screen only.
6653        final DisplayContent displayContent = getDefaultDisplayContentLocked();
6654
6655        // Use the effective "visual" dimensions based on current rotation
6656        final boolean rotated = (mRotation == Surface.ROTATION_90
6657                || mRotation == Surface.ROTATION_270);
6658        final int realdw = rotated ?
6659                displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth;
6660        final int realdh = rotated ?
6661                displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight;
6662        int dw = realdw;
6663        int dh = realdh;
6664
6665        if (mAltOrientation) {
6666            if (realdw > realdh) {
6667                // Turn landscape into portrait.
6668                int maxw = (int)(realdh/1.3f);
6669                if (maxw < realdw) {
6670                    dw = maxw;
6671                }
6672            } else {
6673                // Turn portrait into landscape.
6674                int maxh = (int)(realdw/1.3f);
6675                if (maxh < realdh) {
6676                    dh = maxh;
6677                }
6678            }
6679        }
6680
6681        if (config != null) {
6682            config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT :
6683                    Configuration.ORIENTATION_LANDSCAPE;
6684        }
6685
6686        // Update application display metrics.
6687        final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation);
6688        final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation);
6689        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
6690        synchronized(displayContent.mDisplaySizeLock) {
6691            displayInfo.rotation = mRotation;
6692            displayInfo.logicalWidth = dw;
6693            displayInfo.logicalHeight = dh;
6694            displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity;
6695            displayInfo.appWidth = appWidth;
6696            displayInfo.appHeight = appHeight;
6697            displayInfo.getLogicalMetrics(mRealDisplayMetrics,
6698                    CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
6699            displayInfo.getAppMetrics(mDisplayMetrics);
6700            mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
6701                    displayContent.getDisplayId(), displayInfo);
6702        }
6703        if (false) {
6704            Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight);
6705        }
6706
6707        final DisplayMetrics dm = mDisplayMetrics;
6708        mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm,
6709                mCompatDisplayMetrics);
6710
6711        if (config != null) {
6712            config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation)
6713                    / dm.density);
6714            config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation)
6715                    / dm.density);
6716            computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, dm.density, config);
6717
6718            config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale);
6719            config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale);
6720            config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh);
6721            config.densityDpi = displayContent.mBaseDisplayDensity;
6722
6723            // Update the configuration based on available input devices, lid switch,
6724            // and platform configuration.
6725            config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
6726            config.keyboard = Configuration.KEYBOARD_NOKEYS;
6727            config.navigation = Configuration.NAVIGATION_NONAV;
6728
6729            int keyboardPresence = 0;
6730            int navigationPresence = 0;
6731            final InputDevice[] devices = mInputManager.getInputDevices();
6732            final int len = devices.length;
6733            for (int i = 0; i < len; i++) {
6734                InputDevice device = devices[i];
6735                if (!device.isVirtual()) {
6736                    final int sources = device.getSources();
6737                    final int presenceFlag = device.isExternal() ?
6738                            WindowManagerPolicy.PRESENCE_EXTERNAL :
6739                                    WindowManagerPolicy.PRESENCE_INTERNAL;
6740
6741                    if (mIsTouchDevice) {
6742                        if ((sources & InputDevice.SOURCE_TOUCHSCREEN) ==
6743                                InputDevice.SOURCE_TOUCHSCREEN) {
6744                            config.touchscreen = Configuration.TOUCHSCREEN_FINGER;
6745                        }
6746                    } else {
6747                        config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
6748                    }
6749
6750                    if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) {
6751                        config.navigation = Configuration.NAVIGATION_TRACKBALL;
6752                        navigationPresence |= presenceFlag;
6753                    } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD
6754                            && config.navigation == Configuration.NAVIGATION_NONAV) {
6755                        config.navigation = Configuration.NAVIGATION_DPAD;
6756                        navigationPresence |= presenceFlag;
6757                    }
6758
6759                    if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {
6760                        config.keyboard = Configuration.KEYBOARD_QWERTY;
6761                        keyboardPresence |= presenceFlag;
6762                    }
6763                }
6764            }
6765
6766            // Determine whether a hard keyboard is available and enabled.
6767            boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS;
6768            if (hardKeyboardAvailable != mHardKeyboardAvailable) {
6769                mHardKeyboardAvailable = hardKeyboardAvailable;
6770                mHardKeyboardEnabled = hardKeyboardAvailable;
6771                mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
6772                mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
6773            }
6774            if (!mHardKeyboardEnabled) {
6775                config.keyboard = Configuration.KEYBOARD_NOKEYS;
6776            }
6777
6778            // Let the policy update hidden states.
6779            config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
6780            config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
6781            config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO;
6782            mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence);
6783        }
6784
6785        return true;
6786    }
6787
6788    public boolean isHardKeyboardAvailable() {
6789        synchronized (mWindowMap) {
6790            return mHardKeyboardAvailable;
6791        }
6792    }
6793
6794    public boolean isHardKeyboardEnabled() {
6795        synchronized (mWindowMap) {
6796            return mHardKeyboardEnabled;
6797        }
6798    }
6799
6800    public void setHardKeyboardEnabled(boolean enabled) {
6801        synchronized (mWindowMap) {
6802            if (mHardKeyboardEnabled != enabled) {
6803                mHardKeyboardEnabled = enabled;
6804                mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
6805            }
6806        }
6807    }
6808
6809    public void setOnHardKeyboardStatusChangeListener(
6810            OnHardKeyboardStatusChangeListener listener) {
6811        synchronized (mWindowMap) {
6812            mHardKeyboardStatusChangeListener = listener;
6813        }
6814    }
6815
6816    void notifyHardKeyboardStatusChange() {
6817        final boolean available, enabled;
6818        final OnHardKeyboardStatusChangeListener listener;
6819        synchronized (mWindowMap) {
6820            listener = mHardKeyboardStatusChangeListener;
6821            available = mHardKeyboardAvailable;
6822            enabled = mHardKeyboardEnabled;
6823        }
6824        if (listener != null) {
6825            listener.onHardKeyboardStatusChange(available, enabled);
6826        }
6827    }
6828
6829    // -------------------------------------------------------------
6830    // Drag and drop
6831    // -------------------------------------------------------------
6832
6833    IBinder prepareDragSurface(IWindow window, SurfaceSession session,
6834            int flags, int width, int height, Surface outSurface) {
6835        if (DEBUG_DRAG) {
6836            Slog.d(TAG, "prepare drag surface: w=" + width + " h=" + height
6837                    + " flags=" + Integer.toHexString(flags) + " win=" + window
6838                    + " asbinder=" + window.asBinder());
6839        }
6840
6841        final int callerPid = Binder.getCallingPid();
6842        final long origId = Binder.clearCallingIdentity();
6843        IBinder token = null;
6844
6845        try {
6846            synchronized (mWindowMap) {
6847                try {
6848                    if (mDragState == null) {
6849                        // TODO(multi-display): support other displays
6850                        final DisplayContent displayContent = getDefaultDisplayContentLocked();
6851                        final Display display = displayContent.getDisplay();
6852                        SurfaceControl surface = new SurfaceControl(session, "drag surface",
6853                                width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
6854                        surface.setLayerStack(display.getLayerStack());
6855                        if (SHOW_TRANSACTIONS) Slog.i(TAG, "  DRAG "
6856                                + surface + ": CREATE");
6857                        outSurface.copyFrom(surface);
6858                        final IBinder winBinder = window.asBinder();
6859                        token = new Binder();
6860                        mDragState = new DragState(this, token, surface, /*flags*/ 0, winBinder);
6861                        token = mDragState.mToken = new Binder();
6862
6863                        // 5 second timeout for this window to actually begin the drag
6864                        mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder);
6865                        Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder);
6866                        mH.sendMessageDelayed(msg, 5000);
6867                    } else {
6868                        Slog.w(TAG, "Drag already in progress");
6869                    }
6870                } catch (OutOfResourcesException e) {
6871                    Slog.e(TAG, "Can't allocate drag surface w=" + width + " h=" + height, e);
6872                    if (mDragState != null) {
6873                        mDragState.reset();
6874                        mDragState = null;
6875                    }
6876                }
6877            }
6878        } finally {
6879            Binder.restoreCallingIdentity(origId);
6880        }
6881
6882        return token;
6883    }
6884
6885    // -------------------------------------------------------------
6886    // Input Events and Focus Management
6887    // -------------------------------------------------------------
6888
6889    final InputMonitor mInputMonitor = new InputMonitor(this);
6890    private boolean mEventDispatchingEnabled;
6891
6892    @Override
6893    public void pauseKeyDispatching(IBinder _token) {
6894        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
6895                "pauseKeyDispatching()")) {
6896            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
6897        }
6898
6899        synchronized (mWindowMap) {
6900            WindowToken token = mTokenMap.get(_token);
6901            if (token != null) {
6902                mInputMonitor.pauseDispatchingLw(token);
6903            }
6904        }
6905    }
6906
6907    @Override
6908    public void resumeKeyDispatching(IBinder _token) {
6909        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
6910                "resumeKeyDispatching()")) {
6911            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
6912        }
6913
6914        synchronized (mWindowMap) {
6915            WindowToken token = mTokenMap.get(_token);
6916            if (token != null) {
6917                mInputMonitor.resumeDispatchingLw(token);
6918            }
6919        }
6920    }
6921
6922    @Override
6923    public void setEventDispatching(boolean enabled) {
6924        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
6925                "setEventDispatching()")) {
6926            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
6927        }
6928
6929        synchronized (mWindowMap) {
6930            mEventDispatchingEnabled = enabled;
6931            if (mDisplayEnabled) {
6932                mInputMonitor.setEventDispatchingLw(enabled);
6933            }
6934            sendScreenStatusToClientsLocked();
6935        }
6936    }
6937
6938    @Override
6939    public IBinder getFocusedWindowToken() {
6940        if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO,
6941                "getFocusedWindowToken()")) {
6942            throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission.");
6943        }
6944        synchronized (mWindowMap) {
6945            WindowState windowState = getFocusedWindowLocked();
6946            if (windowState != null) {
6947                return windowState.mClient.asBinder();
6948            }
6949            return null;
6950        }
6951    }
6952
6953    private WindowState getFocusedWindow() {
6954        synchronized (mWindowMap) {
6955            return getFocusedWindowLocked();
6956        }
6957    }
6958
6959    private WindowState getFocusedWindowLocked() {
6960        return mCurrentFocus;
6961    }
6962
6963    public boolean detectSafeMode() {
6964        if (!mInputMonitor.waitForInputDevicesReady(
6965                INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) {
6966            Slog.w(TAG, "Devices still not ready after waiting "
6967                   + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS
6968                   + " milliseconds before attempting to detect safe mode.");
6969        }
6970
6971        int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
6972                KeyEvent.KEYCODE_MENU);
6973        int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S);
6974        int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD,
6975                KeyEvent.KEYCODE_DPAD_CENTER);
6976        int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL,
6977                InputManagerService.BTN_MOUSE);
6978        int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
6979                KeyEvent.KEYCODE_VOLUME_DOWN);
6980        mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0
6981                || volumeDownState > 0;
6982        try {
6983            if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0) {
6984                mSafeMode = true;
6985                SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, "");
6986            }
6987        } catch (IllegalArgumentException e) {
6988        }
6989        if (mSafeMode) {
6990            Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState
6991                    + " dpad=" + dpadState + " trackball=" + trackballState + ")");
6992        } else {
6993            Log.i(TAG, "SAFE MODE not enabled");
6994        }
6995        mPolicy.setSafeMode(mSafeMode);
6996        return mSafeMode;
6997    }
6998
6999    public void displayReady() {
7000        displayReady(Display.DEFAULT_DISPLAY);
7001
7002        synchronized(mWindowMap) {
7003            final DisplayContent displayContent = getDefaultDisplayContentLocked();
7004            readForcedDisplaySizeAndDensityLocked(displayContent);
7005            mDisplayReady = true;
7006        }
7007
7008        try {
7009            mActivityManager.updateConfiguration(null);
7010        } catch (RemoteException e) {
7011        }
7012
7013        synchronized(mWindowMap) {
7014            mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
7015                    PackageManager.FEATURE_TOUCHSCREEN);
7016            configureDisplayPolicyLocked(getDefaultDisplayContentLocked());
7017        }
7018
7019        try {
7020            mActivityManager.updateConfiguration(null);
7021        } catch (RemoteException e) {
7022        }
7023    }
7024
7025    private void displayReady(int displayId) {
7026        synchronized(mWindowMap) {
7027            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7028            if (displayContent != null) {
7029                mAnimator.addDisplayLocked(displayId);
7030                synchronized(displayContent.mDisplaySizeLock) {
7031                    // Bootstrap the default logical display from the display manager.
7032                    final DisplayInfo displayInfo = displayContent.getDisplayInfo();
7033                    DisplayInfo newDisplayInfo = mDisplayManagerInternal.getDisplayInfo(displayId);
7034                    if (newDisplayInfo != null) {
7035                        displayInfo.copyFrom(newDisplayInfo);
7036                    }
7037                    displayContent.mInitialDisplayWidth = displayInfo.logicalWidth;
7038                    displayContent.mInitialDisplayHeight = displayInfo.logicalHeight;
7039                    displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi;
7040                    displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth;
7041                    displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight;
7042                    displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity;
7043                    displayContent.mBaseDisplayRect.set(0, 0,
7044                            displayContent.mBaseDisplayWidth, displayContent.mBaseDisplayHeight);
7045                }
7046            }
7047        }
7048    }
7049
7050    public void systemReady() {
7051        mPolicy.systemReady();
7052    }
7053
7054    // TODO(multidisplay): Call isScreenOn for each display.
7055    private void sendScreenStatusToClientsLocked() {
7056        final boolean on = mPowerManager.isScreenOn();
7057        final int numDisplays = mDisplayContents.size();
7058        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
7059            final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
7060            final int numWindows = windows.size();
7061            for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
7062                try {
7063                    windows.get(winNdx).mClient.dispatchScreenState(on);
7064                } catch (RemoteException e) {
7065                    // Ignored
7066                }
7067            }
7068        }
7069    }
7070
7071    // -------------------------------------------------------------
7072    // Async Handler
7073    // -------------------------------------------------------------
7074
7075    final class H extends Handler {
7076        public static final int REPORT_FOCUS_CHANGE = 2;
7077        public static final int REPORT_LOSING_FOCUS = 3;
7078        public static final int DO_TRAVERSAL = 4;
7079        public static final int ADD_STARTING = 5;
7080        public static final int REMOVE_STARTING = 6;
7081        public static final int FINISHED_STARTING = 7;
7082        public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8;
7083        public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9;
7084        public static final int WINDOW_FREEZE_TIMEOUT = 11;
7085
7086        public static final int APP_TRANSITION_TIMEOUT = 13;
7087        public static final int PERSIST_ANIMATION_SCALE = 14;
7088        public static final int FORCE_GC = 15;
7089        public static final int ENABLE_SCREEN = 16;
7090        public static final int APP_FREEZE_TIMEOUT = 17;
7091        public static final int SEND_NEW_CONFIGURATION = 18;
7092        public static final int REPORT_WINDOWS_CHANGE = 19;
7093        public static final int DRAG_START_TIMEOUT = 20;
7094        public static final int DRAG_END_TIMEOUT = 21;
7095        public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22;
7096        public static final int BOOT_TIMEOUT = 23;
7097        public static final int WAITING_FOR_DRAWN_TIMEOUT = 24;
7098        public static final int SHOW_STRICT_MODE_VIOLATION = 25;
7099        public static final int DO_ANIMATION_CALLBACK = 26;
7100
7101        public static final int DO_DISPLAY_ADDED = 27;
7102        public static final int DO_DISPLAY_REMOVED = 28;
7103        public static final int DO_DISPLAY_CHANGED = 29;
7104
7105        public static final int CLIENT_FREEZE_TIMEOUT = 30;
7106        public static final int TAP_OUTSIDE_STACK = 31;
7107        public static final int NOTIFY_ACTIVITY_DRAWN = 32;
7108
7109        public static final int REMOVE_STARTING_TIMEOUT = 33;
7110
7111        @Override
7112        public void handleMessage(Message msg) {
7113            if (DEBUG_WINDOW_TRACE) {
7114                Slog.v(TAG, "handleMessage: entry what=" + msg.what);
7115            }
7116            switch (msg.what) {
7117                case REPORT_FOCUS_CHANGE: {
7118                    WindowState lastFocus;
7119                    WindowState newFocus;
7120
7121                    synchronized(mWindowMap) {
7122                        lastFocus = mLastFocus;
7123                        newFocus = mCurrentFocus;
7124                        if (lastFocus == newFocus) {
7125                            // Focus is not changing, so nothing to do.
7126                            return;
7127                        }
7128                        mLastFocus = newFocus;
7129                        if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Focus moving from " + lastFocus +
7130                                " to " + newFocus);
7131                        if (newFocus != null && lastFocus != null
7132                                && !newFocus.isDisplayedLw()) {
7133                            //Slog.i(TAG, "Delaying loss of focus...");
7134                            mLosingFocus.add(lastFocus);
7135                            lastFocus = null;
7136                        }
7137                    }
7138
7139                    //System.out.println("Changing focus from " + lastFocus
7140                    //                   + " to " + newFocus);
7141                    if (newFocus != null) {
7142                        if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Gaining focus: " + newFocus);
7143                        newFocus.reportFocusChangedSerialized(true, mInTouchMode);
7144                        notifyFocusChanged();
7145                    }
7146
7147                    if (lastFocus != null) {
7148                        if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing focus: " + lastFocus);
7149                        lastFocus.reportFocusChangedSerialized(false, mInTouchMode);
7150                    }
7151                } break;
7152
7153                case REPORT_LOSING_FOCUS: {
7154                    ArrayList<WindowState> losers;
7155
7156                    synchronized(mWindowMap) {
7157                        losers = mLosingFocus;
7158                        mLosingFocus = new ArrayList<WindowState>();
7159                    }
7160
7161                    final int N = losers.size();
7162                    for (int i=0; i<N; i++) {
7163                        if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing delayed focus: " +
7164                                losers.get(i));
7165                        losers.get(i).reportFocusChangedSerialized(false, mInTouchMode);
7166                    }
7167                } break;
7168
7169                case DO_TRAVERSAL: {
7170                    synchronized(mWindowMap) {
7171                        mTraversalScheduled = false;
7172                        performLayoutAndPlaceSurfacesLocked();
7173                    }
7174                } break;
7175
7176                case ADD_STARTING: {
7177                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7178                    final StartingData sd = wtoken.startingData;
7179
7180                    if (sd == null) {
7181                        // Animation has been canceled... do nothing.
7182                        return;
7183                    }
7184
7185                    if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting "
7186                            + wtoken + ": pkg=" + sd.pkg);
7187
7188                    View view = null;
7189                    try {
7190                        view = mPolicy.addStartingWindow(
7191                            wtoken.token, sd.pkg, sd.theme, sd.compatInfo,
7192                            sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo, sd.windowFlags);
7193                    } catch (Exception e) {
7194                        Slog.w(TAG, "Exception when adding starting window", e);
7195                    }
7196
7197                    if (view != null) {
7198                        boolean abort = false;
7199
7200                        synchronized(mWindowMap) {
7201                            if (wtoken.removed || wtoken.startingData == null) {
7202                                // If the window was successfully added, then
7203                                // we need to remove it.
7204                                if (wtoken.startingWindow != null) {
7205                                    if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
7206                                            "Aborted starting " + wtoken
7207                                            + ": removed=" + wtoken.removed
7208                                            + " startingData=" + wtoken.startingData);
7209                                    removeStartingWindowTimeout(wtoken);
7210                                    wtoken.startingWindow = null;
7211                                    wtoken.startingData = null;
7212                                    abort = true;
7213                                }
7214                            } else {
7215                                wtoken.startingView = view;
7216                            }
7217                            if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG,
7218                                    "Added starting " + wtoken
7219                                    + ": startingWindow="
7220                                    + wtoken.startingWindow + " startingView="
7221                                    + wtoken.startingView);
7222                        }
7223
7224                        if (abort) {
7225                            try {
7226                                mPolicy.removeStartingWindow(wtoken.token, view);
7227                            } catch (Exception e) {
7228                                Slog.w(TAG, "Exception when removing starting window", e);
7229                            }
7230                        }
7231                    }
7232                } break;
7233
7234                case REMOVE_STARTING_TIMEOUT: {
7235                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7236                    Slog.e(TAG, "Starting window " + wtoken + " timed out");
7237                    // Fall through.
7238                }
7239                case REMOVE_STARTING: {
7240                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7241                    IBinder token = null;
7242                    View view = null;
7243                    synchronized (mWindowMap) {
7244                        if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting "
7245                                + wtoken + ": startingWindow="
7246                                + wtoken.startingWindow + " startingView="
7247                                + wtoken.startingView);
7248                        if (wtoken.startingWindow != null) {
7249                            view = wtoken.startingView;
7250                            token = wtoken.token;
7251                            wtoken.startingData = null;
7252                            wtoken.startingView = null;
7253                            wtoken.startingWindow = null;
7254                            wtoken.startingDisplayed = false;
7255                        }
7256                    }
7257                    if (view != null) {
7258                        try {
7259                            mPolicy.removeStartingWindow(token, view);
7260                        } catch (Exception e) {
7261                            Slog.w(TAG, "Exception when removing starting window", e);
7262                        }
7263                    }
7264                } break;
7265
7266                case FINISHED_STARTING: {
7267                    IBinder token = null;
7268                    View view = null;
7269                    while (true) {
7270                        synchronized (mWindowMap) {
7271                            final int N = mFinishedStarting.size();
7272                            if (N <= 0) {
7273                                break;
7274                            }
7275                            AppWindowToken wtoken = mFinishedStarting.remove(N-1);
7276
7277                            if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
7278                                    "Finished starting " + wtoken
7279                                    + ": startingWindow=" + wtoken.startingWindow
7280                                    + " startingView=" + wtoken.startingView);
7281
7282                            if (wtoken.startingWindow == null) {
7283                                continue;
7284                            }
7285
7286                            view = wtoken.startingView;
7287                            token = wtoken.token;
7288                            wtoken.startingData = null;
7289                            wtoken.startingView = null;
7290                            wtoken.startingWindow = null;
7291                            wtoken.startingDisplayed = false;
7292                        }
7293
7294                        try {
7295                            mPolicy.removeStartingWindow(token, view);
7296                        } catch (Exception e) {
7297                            Slog.w(TAG, "Exception when removing starting window", e);
7298                        }
7299                    }
7300                } break;
7301
7302                case REPORT_APPLICATION_TOKEN_DRAWN: {
7303                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7304
7305                    try {
7306                        if (DEBUG_VISIBILITY) Slog.v(
7307                                TAG, "Reporting drawn in " + wtoken);
7308                        wtoken.appToken.windowsDrawn();
7309                    } catch (RemoteException ex) {
7310                    }
7311                } break;
7312
7313                case REPORT_APPLICATION_TOKEN_WINDOWS: {
7314                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7315
7316                    boolean nowVisible = msg.arg1 != 0;
7317                    boolean nowGone = msg.arg2 != 0;
7318
7319                    try {
7320                        if (DEBUG_VISIBILITY) Slog.v(
7321                                TAG, "Reporting visible in " + wtoken
7322                                + " visible=" + nowVisible
7323                                + " gone=" + nowGone);
7324                        if (nowVisible) {
7325                            wtoken.appToken.windowsVisible();
7326                        } else {
7327                            wtoken.appToken.windowsGone();
7328                        }
7329                    } catch (RemoteException ex) {
7330                    }
7331                } break;
7332
7333                case WINDOW_FREEZE_TIMEOUT: {
7334                    // TODO(multidisplay): Can non-default displays rotate?
7335                    synchronized (mWindowMap) {
7336                        Slog.w(TAG, "Window freeze timeout expired.");
7337                        final WindowList windows = getDefaultWindowListLocked();
7338                        int i = windows.size();
7339                        while (i > 0) {
7340                            i--;
7341                            WindowState w = windows.get(i);
7342                            if (w.mOrientationChanging) {
7343                                w.mOrientationChanging = false;
7344                                w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
7345                                        - mDisplayFreezeTime);
7346                                Slog.w(TAG, "Force clearing orientation change: " + w);
7347                            }
7348                        }
7349                        performLayoutAndPlaceSurfacesLocked();
7350                    }
7351                    break;
7352                }
7353
7354                case APP_TRANSITION_TIMEOUT: {
7355                    synchronized (mWindowMap) {
7356                        if (mAppTransition.isTransitionSet()) {
7357                            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** APP TRANSITION TIMEOUT");
7358                            mAppTransition.setTimeout();
7359                            performLayoutAndPlaceSurfacesLocked();
7360                        }
7361                    }
7362                    break;
7363                }
7364
7365                case PERSIST_ANIMATION_SCALE: {
7366                    Settings.Global.putFloat(mContext.getContentResolver(),
7367                            Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
7368                    Settings.Global.putFloat(mContext.getContentResolver(),
7369                            Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
7370                    Settings.Global.putFloat(mContext.getContentResolver(),
7371                            Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScale);
7372                    break;
7373                }
7374
7375                case FORCE_GC: {
7376                    synchronized (mWindowMap) {
7377                        // Since we're holding both mWindowMap and mAnimator we don't need to
7378                        // hold mAnimator.mLayoutToAnim.
7379                        if (mAnimator.mAnimating || mAnimationScheduled) {
7380                            // If we are animating, don't do the gc now but
7381                            // delay a bit so we don't interrupt the animation.
7382                            sendEmptyMessageDelayed(H.FORCE_GC, 2000);
7383                            return;
7384                        }
7385                        // If we are currently rotating the display, it will
7386                        // schedule a new message when done.
7387                        if (mDisplayFrozen) {
7388                            return;
7389                        }
7390                    }
7391                    Runtime.getRuntime().gc();
7392                    break;
7393                }
7394
7395                case ENABLE_SCREEN: {
7396                    performEnableScreen();
7397                    break;
7398                }
7399
7400                case APP_FREEZE_TIMEOUT: {
7401                    synchronized (mWindowMap) {
7402                        Slog.w(TAG, "App freeze timeout expired.");
7403                        final int numStacks = mStackIdToStack.size();
7404                        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
7405                            final TaskStack stack = mStackIdToStack.valueAt(stackNdx);
7406                            final ArrayList<Task> tasks = stack.getTasks();
7407                            for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
7408                                AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
7409                                for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
7410                                    AppWindowToken tok = tokens.get(tokenNdx);
7411                                    if (tok.mAppAnimator.freezingScreen) {
7412                                        Slog.w(TAG, "Force clearing freeze: " + tok);
7413                                        unsetAppFreezingScreenLocked(tok, true, true);
7414                                    }
7415                                }
7416                            }
7417                        }
7418                    }
7419                    break;
7420                }
7421
7422                case CLIENT_FREEZE_TIMEOUT: {
7423                    synchronized (mWindowMap) {
7424                        if (mClientFreezingScreen) {
7425                            mClientFreezingScreen = false;
7426                            mLastFinishedFreezeSource = "client-timeout";
7427                            stopFreezingDisplayLocked();
7428                        }
7429                    }
7430                    break;
7431                }
7432
7433                case SEND_NEW_CONFIGURATION: {
7434                    removeMessages(SEND_NEW_CONFIGURATION);
7435                    sendNewConfiguration();
7436                    break;
7437                }
7438
7439                case REPORT_WINDOWS_CHANGE: {
7440                    if (mWindowsChanged) {
7441                        synchronized (mWindowMap) {
7442                            mWindowsChanged = false;
7443                        }
7444                        notifyWindowsChanged();
7445                    }
7446                    break;
7447                }
7448
7449                case DRAG_START_TIMEOUT: {
7450                    IBinder win = (IBinder)msg.obj;
7451                    if (DEBUG_DRAG) {
7452                        Slog.w(TAG, "Timeout starting drag by win " + win);
7453                    }
7454                    synchronized (mWindowMap) {
7455                        // !!! TODO: ANR the app that has failed to start the drag in time
7456                        if (mDragState != null) {
7457                            mDragState.unregister();
7458                            mInputMonitor.updateInputWindowsLw(true /*force*/);
7459                            mDragState.reset();
7460                            mDragState = null;
7461                        }
7462                    }
7463                    break;
7464                }
7465
7466                case DRAG_END_TIMEOUT: {
7467                    IBinder win = (IBinder)msg.obj;
7468                    if (DEBUG_DRAG) {
7469                        Slog.w(TAG, "Timeout ending drag to win " + win);
7470                    }
7471                    synchronized (mWindowMap) {
7472                        // !!! TODO: ANR the drag-receiving app
7473                        if (mDragState != null) {
7474                            mDragState.mDragResult = false;
7475                            mDragState.endDragLw();
7476                        }
7477                    }
7478                    break;
7479                }
7480
7481                case REPORT_HARD_KEYBOARD_STATUS_CHANGE: {
7482                    notifyHardKeyboardStatusChange();
7483                    break;
7484                }
7485
7486                case BOOT_TIMEOUT: {
7487                    performBootTimeout();
7488                    break;
7489                }
7490
7491                case WAITING_FOR_DRAWN_TIMEOUT: {
7492                    Pair<WindowState, IRemoteCallback> pair;
7493                    synchronized (mWindowMap) {
7494                        pair = (Pair<WindowState, IRemoteCallback>)msg.obj;
7495                        Slog.w(TAG, "Timeout waiting for drawn: " + pair.first);
7496                        if (!mWaitingForDrawn.remove(pair)) {
7497                            return;
7498                        }
7499                    }
7500                    try {
7501                        pair.second.sendResult(null);
7502                    } catch (RemoteException e) {
7503                    }
7504                    break;
7505                }
7506
7507                case SHOW_STRICT_MODE_VIOLATION: {
7508                    showStrictModeViolation(msg.arg1, msg.arg2);
7509                    break;
7510                }
7511
7512                case DO_ANIMATION_CALLBACK: {
7513                    try {
7514                        ((IRemoteCallback)msg.obj).sendResult(null);
7515                    } catch (RemoteException e) {
7516                    }
7517                    break;
7518                }
7519
7520                case DO_DISPLAY_ADDED:
7521                    handleDisplayAdded(msg.arg1);
7522                    break;
7523
7524                case DO_DISPLAY_REMOVED:
7525                    synchronized (mWindowMap) {
7526                        handleDisplayRemovedLocked(msg.arg1);
7527                    }
7528                    break;
7529
7530                case DO_DISPLAY_CHANGED:
7531                    synchronized (mWindowMap) {
7532                        handleDisplayChangedLocked(msg.arg1);
7533                    }
7534                    break;
7535
7536                case TAP_OUTSIDE_STACK: {
7537                    int stackId;
7538                    synchronized (mWindowMap) {
7539                        stackId = ((DisplayContent)msg.obj).stackIdFromPoint(msg.arg1, msg.arg2);
7540                    }
7541                    if (stackId >= 0) {
7542                        try {
7543                            mActivityManager.setFocusedStack(stackId);
7544                        } catch (RemoteException e) {
7545                        }
7546                    }
7547                }
7548                break;
7549                case NOTIFY_ACTIVITY_DRAWN:
7550                    try {
7551                        mActivityManager.notifyActivityDrawn((IBinder) msg.obj);
7552                    } catch (RemoteException e) {
7553                    }
7554                    break;
7555            }
7556            if (DEBUG_WINDOW_TRACE) {
7557                Slog.v(TAG, "handleMessage: exit");
7558            }
7559        }
7560    }
7561
7562    // -------------------------------------------------------------
7563    // IWindowManager API
7564    // -------------------------------------------------------------
7565
7566    @Override
7567    public IWindowSession openSession(IInputMethodClient client,
7568            IInputContext inputContext) {
7569        if (client == null) throw new IllegalArgumentException("null client");
7570        if (inputContext == null) throw new IllegalArgumentException("null inputContext");
7571        Session session = new Session(this, client, inputContext);
7572        return session;
7573    }
7574
7575    @Override
7576    public boolean inputMethodClientHasFocus(IInputMethodClient client) {
7577        synchronized (mWindowMap) {
7578            // The focus for the client is the window immediately below
7579            // where we would place the input method window.
7580            int idx = findDesiredInputMethodWindowIndexLocked(false);
7581            if (idx > 0) {
7582                // TODO(multidisplay): IMEs are only supported on the default display.
7583                WindowState imFocus = getDefaultWindowListLocked().get(idx-1);
7584                if (DEBUG_INPUT_METHOD) {
7585                    Slog.i(TAG, "Desired input method target: " + imFocus);
7586                    Slog.i(TAG, "Current focus: " + mCurrentFocus);
7587                    Slog.i(TAG, "Last focus: " + mLastFocus);
7588                }
7589                if (imFocus != null) {
7590                    // This may be a starting window, in which case we still want
7591                    // to count it as okay.
7592                    if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING
7593                            && imFocus.mAppToken != null) {
7594                        // The client has definitely started, so it really should
7595                        // have a window in this app token.  Let's look for it.
7596                        for (int i=0; i<imFocus.mAppToken.windows.size(); i++) {
7597                            WindowState w = imFocus.mAppToken.windows.get(i);
7598                            if (w != imFocus) {
7599                                Log.i(TAG, "Switching to real app window: " + w);
7600                                imFocus = w;
7601                                break;
7602                            }
7603                        }
7604                    }
7605                    if (DEBUG_INPUT_METHOD) {
7606                        Slog.i(TAG, "IM target client: " + imFocus.mSession.mClient);
7607                        if (imFocus.mSession.mClient != null) {
7608                            Slog.i(TAG, "IM target client binder: "
7609                                    + imFocus.mSession.mClient.asBinder());
7610                            Slog.i(TAG, "Requesting client binder: " + client.asBinder());
7611                        }
7612                    }
7613                    if (imFocus.mSession.mClient != null &&
7614                            imFocus.mSession.mClient.asBinder() == client.asBinder()) {
7615                        return true;
7616                    }
7617                }
7618            }
7619
7620            // Okay, how about this...  what is the current focus?
7621            // It seems in some cases we may not have moved the IM
7622            // target window, such as when it was in a pop-up window,
7623            // so let's also look at the current focus.  (An example:
7624            // go to Gmail, start searching so the keyboard goes up,
7625            // press home.  Sometimes the IME won't go down.)
7626            // Would be nice to fix this more correctly, but it's
7627            // way at the end of a release, and this should be good enough.
7628            if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null
7629                    && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) {
7630                return true;
7631            }
7632        }
7633        return false;
7634    }
7635
7636    @Override
7637    public void getInitialDisplaySize(int displayId, Point size) {
7638        synchronized (mWindowMap) {
7639            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7640            if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
7641                synchronized(displayContent.mDisplaySizeLock) {
7642                    size.x = displayContent.mInitialDisplayWidth;
7643                    size.y = displayContent.mInitialDisplayHeight;
7644                }
7645            }
7646        }
7647    }
7648
7649    @Override
7650    public void getBaseDisplaySize(int displayId, Point size) {
7651        synchronized (mWindowMap) {
7652            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7653            if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
7654                synchronized(displayContent.mDisplaySizeLock) {
7655                    size.x = displayContent.mBaseDisplayWidth;
7656                    size.y = displayContent.mBaseDisplayHeight;
7657                }
7658            }
7659        }
7660    }
7661
7662    @Override
7663    public void setForcedDisplaySize(int displayId, int width, int height) {
7664        if (mContext.checkCallingOrSelfPermission(
7665                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7666                PackageManager.PERMISSION_GRANTED) {
7667            throw new SecurityException("Must hold permission " +
7668                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
7669        }
7670        if (displayId != Display.DEFAULT_DISPLAY) {
7671            throw new IllegalArgumentException("Can only set the default display");
7672        }
7673        final long ident = Binder.clearCallingIdentity();
7674        try {
7675            synchronized(mWindowMap) {
7676                // Set some sort of reasonable bounds on the size of the display that we
7677                // will try to emulate.
7678                final int MIN_WIDTH = 200;
7679                final int MIN_HEIGHT = 200;
7680                final int MAX_SCALE = 2;
7681                final DisplayContent displayContent = getDisplayContentLocked(displayId);
7682                if (displayContent != null) {
7683                    width = Math.min(Math.max(width, MIN_WIDTH),
7684                            displayContent.mInitialDisplayWidth * MAX_SCALE);
7685                    height = Math.min(Math.max(height, MIN_HEIGHT),
7686                            displayContent.mInitialDisplayHeight * MAX_SCALE);
7687                    setForcedDisplaySizeLocked(displayContent, width, height);
7688                    Settings.Global.putString(mContext.getContentResolver(),
7689                            Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height);
7690                }
7691            }
7692        } finally {
7693            Binder.restoreCallingIdentity(ident);
7694        }
7695    }
7696
7697    private void readForcedDisplaySizeAndDensityLocked(final DisplayContent displayContent) {
7698        String sizeStr = Settings.Global.getString(mContext.getContentResolver(),
7699                Settings.Global.DISPLAY_SIZE_FORCED);
7700        if (sizeStr == null || sizeStr.length() == 0) {
7701            sizeStr = SystemProperties.get(SIZE_OVERRIDE, null);
7702        }
7703        if (sizeStr != null && sizeStr.length() > 0) {
7704            final int pos = sizeStr.indexOf(',');
7705            if (pos > 0 && sizeStr.lastIndexOf(',') == pos) {
7706                int width, height;
7707                try {
7708                    width = Integer.parseInt(sizeStr.substring(0, pos));
7709                    height = Integer.parseInt(sizeStr.substring(pos+1));
7710                    synchronized(displayContent.mDisplaySizeLock) {
7711                        if (displayContent.mBaseDisplayWidth != width
7712                                || displayContent.mBaseDisplayHeight != height) {
7713                            Slog.i(TAG, "FORCED DISPLAY SIZE: " + width + "x" + height);
7714                            displayContent.mBaseDisplayWidth = width;
7715                            displayContent.mBaseDisplayHeight = height;
7716                        }
7717                    }
7718                } catch (NumberFormatException ex) {
7719                }
7720            }
7721        }
7722        String densityStr = Settings.Global.getString(mContext.getContentResolver(),
7723                Settings.Global.DISPLAY_DENSITY_FORCED);
7724        if (densityStr == null || densityStr.length() == 0) {
7725            densityStr = SystemProperties.get(DENSITY_OVERRIDE, null);
7726        }
7727        if (densityStr != null && densityStr.length() > 0) {
7728            int density;
7729            try {
7730                density = Integer.parseInt(densityStr);
7731                synchronized(displayContent.mDisplaySizeLock) {
7732                    if (displayContent.mBaseDisplayDensity != density) {
7733                        Slog.i(TAG, "FORCED DISPLAY DENSITY: " + density);
7734                        displayContent.mBaseDisplayDensity = density;
7735                    }
7736                }
7737            } catch (NumberFormatException ex) {
7738            }
7739        }
7740    }
7741
7742    // displayContent must not be null
7743    private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {
7744        Slog.i(TAG, "Using new display size: " + width + "x" + height);
7745
7746        synchronized(displayContent.mDisplaySizeLock) {
7747            displayContent.mBaseDisplayWidth = width;
7748            displayContent.mBaseDisplayHeight = height;
7749        }
7750        reconfigureDisplayLocked(displayContent);
7751    }
7752
7753    @Override
7754    public void clearForcedDisplaySize(int displayId) {
7755        if (mContext.checkCallingOrSelfPermission(
7756                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7757                PackageManager.PERMISSION_GRANTED) {
7758            throw new SecurityException("Must hold permission " +
7759                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
7760        }
7761        if (displayId != Display.DEFAULT_DISPLAY) {
7762            throw new IllegalArgumentException("Can only set the default display");
7763        }
7764        final long ident = Binder.clearCallingIdentity();
7765        try {
7766            synchronized(mWindowMap) {
7767                final DisplayContent displayContent = getDisplayContentLocked(displayId);
7768                if (displayContent != null) {
7769                    setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
7770                            displayContent.mInitialDisplayHeight);
7771                    Settings.Global.putString(mContext.getContentResolver(),
7772                            Settings.Global.DISPLAY_SIZE_FORCED, "");
7773                }
7774            }
7775        } finally {
7776            Binder.restoreCallingIdentity(ident);
7777        }
7778    }
7779
7780    @Override
7781    public int getInitialDisplayDensity(int displayId) {
7782        synchronized (mWindowMap) {
7783            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7784            if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
7785                synchronized(displayContent.mDisplaySizeLock) {
7786                    return displayContent.mInitialDisplayDensity;
7787                }
7788            }
7789        }
7790        return -1;
7791    }
7792
7793    @Override
7794    public int getBaseDisplayDensity(int displayId) {
7795        synchronized (mWindowMap) {
7796            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7797            if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
7798                synchronized(displayContent.mDisplaySizeLock) {
7799                    return displayContent.mBaseDisplayDensity;
7800                }
7801            }
7802        }
7803        return -1;
7804    }
7805
7806    @Override
7807    public void setForcedDisplayDensity(int displayId, int density) {
7808        if (mContext.checkCallingOrSelfPermission(
7809                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7810                PackageManager.PERMISSION_GRANTED) {
7811            throw new SecurityException("Must hold permission " +
7812                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
7813        }
7814        if (displayId != Display.DEFAULT_DISPLAY) {
7815            throw new IllegalArgumentException("Can only set the default display");
7816        }
7817        final long ident = Binder.clearCallingIdentity();
7818        try {
7819            synchronized(mWindowMap) {
7820                final DisplayContent displayContent = getDisplayContentLocked(displayId);
7821                if (displayContent != null) {
7822                    setForcedDisplayDensityLocked(displayContent, density);
7823                    Settings.Global.putString(mContext.getContentResolver(),
7824                            Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density));
7825                }
7826            }
7827        } finally {
7828            Binder.restoreCallingIdentity(ident);
7829        }
7830    }
7831
7832    // displayContent must not be null
7833    private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) {
7834        Slog.i(TAG, "Using new display density: " + density);
7835
7836        synchronized(displayContent.mDisplaySizeLock) {
7837            displayContent.mBaseDisplayDensity = density;
7838        }
7839        reconfigureDisplayLocked(displayContent);
7840    }
7841
7842    @Override
7843    public void clearForcedDisplayDensity(int displayId) {
7844        if (mContext.checkCallingOrSelfPermission(
7845                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7846                PackageManager.PERMISSION_GRANTED) {
7847            throw new SecurityException("Must hold permission " +
7848                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
7849        }
7850        if (displayId != Display.DEFAULT_DISPLAY) {
7851            throw new IllegalArgumentException("Can only set the default display");
7852        }
7853        final long ident = Binder.clearCallingIdentity();
7854        try {
7855            synchronized(mWindowMap) {
7856                final DisplayContent displayContent = getDisplayContentLocked(displayId);
7857                if (displayContent != null) {
7858                    setForcedDisplayDensityLocked(displayContent,
7859                            displayContent.mInitialDisplayDensity);
7860                    Settings.Global.putString(mContext.getContentResolver(),
7861                            Settings.Global.DISPLAY_DENSITY_FORCED, "");
7862                }
7863            }
7864        } finally {
7865            Binder.restoreCallingIdentity(ident);
7866        }
7867    }
7868
7869    // displayContent must not be null
7870    private void reconfigureDisplayLocked(DisplayContent displayContent) {
7871        // TODO: Multidisplay: for now only use with default display.
7872        configureDisplayPolicyLocked(displayContent);
7873        displayContent.layoutNeeded = true;
7874
7875        boolean configChanged = updateOrientationFromAppTokensLocked(false);
7876        mTempConfiguration.setToDefaults();
7877        mTempConfiguration.fontScale = mCurConfiguration.fontScale;
7878        if (computeScreenConfigurationLocked(mTempConfiguration)) {
7879            if (mCurConfiguration.diff(mTempConfiguration) != 0) {
7880                configChanged = true;
7881            }
7882        }
7883
7884        if (configChanged) {
7885            mWaitingForConfig = true;
7886            startFreezingDisplayLocked(false, 0, 0);
7887            mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
7888        }
7889
7890        performLayoutAndPlaceSurfacesLocked();
7891    }
7892
7893    private void configureDisplayPolicyLocked(DisplayContent displayContent) {
7894        mPolicy.setInitialDisplaySize(displayContent.getDisplay(),
7895                displayContent.mBaseDisplayWidth,
7896                displayContent.mBaseDisplayHeight,
7897                displayContent.mBaseDisplayDensity);
7898
7899        DisplayInfo displayInfo = displayContent.getDisplayInfo();
7900        mPolicy.setDisplayOverscan(displayContent.getDisplay(),
7901                displayInfo.overscanLeft, displayInfo.overscanTop,
7902                displayInfo.overscanRight, displayInfo.overscanBottom);
7903    }
7904
7905    @Override
7906    public void setOverscan(int displayId, int left, int top, int right, int bottom) {
7907        if (mContext.checkCallingOrSelfPermission(
7908                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7909                PackageManager.PERMISSION_GRANTED) {
7910            throw new SecurityException("Must hold permission " +
7911                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
7912        }
7913        final long ident = Binder.clearCallingIdentity();
7914        try {
7915            synchronized(mWindowMap) {
7916                DisplayContent displayContent = getDisplayContentLocked(displayId);
7917                if (displayContent != null) {
7918                    setOverscanLocked(displayContent, left, top, right, bottom);
7919                }
7920            }
7921        } finally {
7922            Binder.restoreCallingIdentity(ident);
7923        }
7924    }
7925
7926    private void setOverscanLocked(DisplayContent displayContent,
7927            int left, int top, int right, int bottom) {
7928        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
7929        synchronized (displayContent.mDisplaySizeLock) {
7930            displayInfo.overscanLeft = left;
7931            displayInfo.overscanTop = top;
7932            displayInfo.overscanRight = right;
7933            displayInfo.overscanBottom = bottom;
7934        }
7935
7936        mDisplaySettings.setOverscanLocked(displayInfo.name, left, top, right, bottom);
7937        mDisplaySettings.writeSettingsLocked();
7938
7939        reconfigureDisplayLocked(displayContent);
7940    }
7941
7942    // -------------------------------------------------------------
7943    // Internals
7944    // -------------------------------------------------------------
7945
7946    final WindowState windowForClientLocked(Session session, IWindow client,
7947            boolean throwOnError) {
7948        return windowForClientLocked(session, client.asBinder(), throwOnError);
7949    }
7950
7951    final WindowState windowForClientLocked(Session session, IBinder client,
7952            boolean throwOnError) {
7953        WindowState win = mWindowMap.get(client);
7954        if (localLOGV) Slog.v(
7955            TAG, "Looking up client " + client + ": " + win);
7956        if (win == null) {
7957            RuntimeException ex = new IllegalArgumentException(
7958                    "Requested window " + client + " does not exist");
7959            if (throwOnError) {
7960                throw ex;
7961            }
7962            Slog.w(TAG, "Failed looking up window", ex);
7963            return null;
7964        }
7965        if (session != null && win.mSession != session) {
7966            RuntimeException ex = new IllegalArgumentException(
7967                    "Requested window " + client + " is in session " +
7968                    win.mSession + ", not " + session);
7969            if (throwOnError) {
7970                throw ex;
7971            }
7972            Slog.w(TAG, "Failed looking up window", ex);
7973            return null;
7974        }
7975
7976        return win;
7977    }
7978
7979    final void rebuildAppWindowListLocked() {
7980        rebuildAppWindowListLocked(getDefaultDisplayContentLocked());
7981    }
7982
7983    private void rebuildAppWindowListLocked(final DisplayContent displayContent) {
7984        final WindowList windows = displayContent.getWindowList();
7985        int NW = windows.size();
7986        int i;
7987        int lastBelow = -1;
7988        int numRemoved = 0;
7989
7990        if (mRebuildTmp.length < NW) {
7991            mRebuildTmp = new WindowState[NW+10];
7992        }
7993
7994        // First remove all existing app windows.
7995        i=0;
7996        while (i < NW) {
7997            WindowState w = windows.get(i);
7998            if (w.mAppToken != null) {
7999                WindowState win = windows.remove(i);
8000                win.mRebuilding = true;
8001                mRebuildTmp[numRemoved] = win;
8002                mWindowsChanged = true;
8003                if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Rebuild removing window: " + win);
8004                NW--;
8005                numRemoved++;
8006                continue;
8007            } else if (lastBelow == i-1) {
8008                if (w.mAttrs.type == TYPE_WALLPAPER || w.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
8009                    lastBelow = i;
8010                }
8011            }
8012            i++;
8013        }
8014
8015        // Keep whatever windows were below the app windows still below,
8016        // by skipping them.
8017        lastBelow++;
8018        i = lastBelow;
8019
8020        // First add all of the exiting app tokens...  these are no longer
8021        // in the main app list, but still have windows shown.  We put them
8022        // in the back because now that the animation is over we no longer
8023        // will care about them.
8024        final ArrayList<TaskStack> stacks = displayContent.getStacks();
8025        final int numStacks = stacks.size();
8026        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
8027            AppTokenList exitingAppTokens = stacks.get(stackNdx).mExitingAppTokens;
8028            int NT = exitingAppTokens.size();
8029            for (int j = 0; j < NT; j++) {
8030                i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j));
8031            }
8032        }
8033
8034        // And add in the still active app tokens in Z order.
8035        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
8036            final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
8037            final int numTasks = tasks.size();
8038            for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
8039                final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
8040                final int numTokens = tokens.size();
8041                for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
8042                    final AppWindowToken wtoken = tokens.get(tokenNdx);
8043                    i = reAddAppWindowsLocked(displayContent, i, wtoken);
8044                }
8045            }
8046        }
8047
8048        i -= lastBelow;
8049        if (i != numRemoved) {
8050            Slog.w(TAG, "On display=" + displayContent.getDisplayId() + " Rebuild removed " +
8051                    numRemoved + " windows but added " + i,
8052                    new RuntimeException("here").fillInStackTrace());
8053            for (i=0; i<numRemoved; i++) {
8054                WindowState ws = mRebuildTmp[i];
8055                if (ws.mRebuilding) {
8056                    StringWriter sw = new StringWriter();
8057                    PrintWriter pw = new FastPrintWriter(sw, false, 1024);
8058                    ws.dump(pw, "", true);
8059                    pw.flush();
8060                    Slog.w(TAG, "This window was lost: " + ws);
8061                    Slog.w(TAG, sw.toString());
8062                    ws.mWinAnimator.destroySurfaceLocked();
8063                }
8064            }
8065            Slog.w(TAG, "Current app token list:");
8066            dumpAppTokensLocked();
8067            Slog.w(TAG, "Final window list:");
8068            dumpWindowsLocked();
8069        }
8070    }
8071
8072    private final void assignLayersLocked(WindowList windows) {
8073        int N = windows.size();
8074        int curBaseLayer = 0;
8075        int curLayer = 0;
8076        int i;
8077
8078        if (DEBUG_LAYERS) Slog.v(TAG, "Assigning layers based on windows=" + windows,
8079                new RuntimeException("here").fillInStackTrace());
8080
8081        boolean anyLayerChanged = false;
8082
8083        for (i=0; i<N; i++) {
8084            final WindowState w = windows.get(i);
8085            final WindowStateAnimator winAnimator = w.mWinAnimator;
8086            boolean layerChanged = false;
8087            int oldLayer = w.mLayer;
8088            if (w.mBaseLayer == curBaseLayer || w.mIsImWindow
8089                    || (i > 0 && w.mIsWallpaper)) {
8090                curLayer += WINDOW_LAYER_MULTIPLIER;
8091                w.mLayer = curLayer;
8092            } else {
8093                curBaseLayer = curLayer = w.mBaseLayer;
8094                w.mLayer = curLayer;
8095            }
8096            if (w.mLayer != oldLayer) {
8097                layerChanged = true;
8098                anyLayerChanged = true;
8099            }
8100            final AppWindowToken wtoken = w.mAppToken;
8101            oldLayer = winAnimator.mAnimLayer;
8102            if (w.mTargetAppToken != null) {
8103                winAnimator.mAnimLayer =
8104                        w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment;
8105            } else if (wtoken != null) {
8106                winAnimator.mAnimLayer =
8107                        w.mLayer + wtoken.mAppAnimator.animLayerAdjustment;
8108            } else {
8109                winAnimator.mAnimLayer = w.mLayer;
8110            }
8111            if (w.mIsImWindow) {
8112                winAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment;
8113            } else if (w.mIsWallpaper) {
8114                winAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment;
8115            }
8116            if (winAnimator.mAnimLayer != oldLayer) {
8117                layerChanged = true;
8118                anyLayerChanged = true;
8119            }
8120            if (layerChanged && w.getStack().isDimming(winAnimator)) {
8121                // Force an animation pass just to update the mDimLayer layer.
8122                scheduleAnimationLocked();
8123            }
8124            if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": "
8125                    + "mBase=" + w.mBaseLayer
8126                    + " mLayer=" + w.mLayer
8127                    + (wtoken == null ?
8128                            "" : " mAppLayer=" + wtoken.mAppAnimator.animLayerAdjustment)
8129                    + " =mAnimLayer=" + winAnimator.mAnimLayer);
8130            //System.out.println(
8131            //    "Assigned layer " + curLayer + " to " + w.mClient.asBinder());
8132        }
8133
8134        //TODO (multidisplay): Magnification is supported only for the default display.
8135        if (mDisplayMagnifier != null && anyLayerChanged
8136                && windows.get(windows.size() - 1).getDisplayId() == Display.DEFAULT_DISPLAY) {
8137            mDisplayMagnifier.onWindowLayersChangedLocked();
8138        }
8139    }
8140
8141    private final void performLayoutAndPlaceSurfacesLocked() {
8142        int loopCount = 6;
8143        do {
8144            mTraversalScheduled = false;
8145            performLayoutAndPlaceSurfacesLockedLoop();
8146            mH.removeMessages(H.DO_TRAVERSAL);
8147            loopCount--;
8148        } while (mTraversalScheduled && loopCount > 0);
8149        mInnerFields.mWallpaperActionPending = false;
8150    }
8151
8152    private boolean mInLayout = false;
8153    private final void performLayoutAndPlaceSurfacesLockedLoop() {
8154        if (mInLayout) {
8155            if (DEBUG) {
8156                throw new RuntimeException("Recursive call!");
8157            }
8158            Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers="
8159                    + Debug.getCallers(3));
8160            return;
8161        }
8162
8163        if (mWaitingForConfig) {
8164            // Our configuration has changed (most likely rotation), but we
8165            // don't yet have the complete configuration to report to
8166            // applications.  Don't do any window layout until we have it.
8167            return;
8168        }
8169
8170        if (!mDisplayReady) {
8171            // Not yet initialized, nothing to do.
8172            return;
8173        }
8174
8175        Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout");
8176        mInLayout = true;
8177        boolean recoveringMemory = false;
8178
8179        try {
8180            if (mForceRemoves != null) {
8181                recoveringMemory = true;
8182                // Wait a little bit for things to settle down, and off we go.
8183                for (int i=0; i<mForceRemoves.size(); i++) {
8184                    WindowState ws = mForceRemoves.get(i);
8185                    Slog.i(TAG, "Force removing: " + ws);
8186                    removeWindowInnerLocked(ws.mSession, ws);
8187                }
8188                mForceRemoves = null;
8189                Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");
8190                Object tmp = new Object();
8191                synchronized (tmp) {
8192                    try {
8193                        tmp.wait(250);
8194                    } catch (InterruptedException e) {
8195                    }
8196                }
8197            }
8198        } catch (RuntimeException e) {
8199            Log.wtf(TAG, "Unhandled exception while force removing for memory", e);
8200        }
8201
8202        try {
8203            performLayoutAndPlaceSurfacesLockedInner(recoveringMemory);
8204
8205            mInLayout = false;
8206
8207            if (needsLayout()) {
8208                if (++mLayoutRepeatCount < 6) {
8209                    requestTraversalLocked();
8210                } else {
8211                    Slog.e(TAG, "Performed 6 layouts in a row. Skipping");
8212                    mLayoutRepeatCount = 0;
8213                }
8214            } else {
8215                mLayoutRepeatCount = 0;
8216            }
8217
8218            if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) {
8219                mH.removeMessages(H.REPORT_WINDOWS_CHANGE);
8220                mH.sendEmptyMessage(H.REPORT_WINDOWS_CHANGE);
8221            }
8222        } catch (RuntimeException e) {
8223            mInLayout = false;
8224            Log.wtf(TAG, "Unhandled exception while laying out windows", e);
8225        }
8226
8227        Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
8228    }
8229
8230    private final void performLayoutLockedInner(final DisplayContent displayContent,
8231                                    boolean initial, boolean updateInputWindows) {
8232        if (!displayContent.layoutNeeded) {
8233            return;
8234        }
8235        displayContent.layoutNeeded = false;
8236        WindowList windows = displayContent.getWindowList();
8237        boolean isDefaultDisplay = displayContent.isDefaultDisplay;
8238
8239        DisplayInfo displayInfo = displayContent.getDisplayInfo();
8240        final int dw = displayInfo.logicalWidth;
8241        final int dh = displayInfo.logicalHeight;
8242
8243        final int NFW = mFakeWindows.size();
8244        for (int i=0; i<NFW; i++) {
8245            mFakeWindows.get(i).layout(dw, dh);
8246        }
8247
8248        final int N = windows.size();
8249        int i;
8250
8251        if (DEBUG_LAYOUT) {
8252            Slog.v(TAG, "-------------------------------------");
8253            Slog.v(TAG, "performLayout: needed="
8254                    + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh);
8255        }
8256
8257        WindowStateAnimator universeBackground = null;
8258
8259        mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mRotation);
8260        if (isDefaultDisplay) {
8261            // Not needed on non-default displays.
8262            mSystemDecorLayer = mPolicy.getSystemDecorLayerLw();
8263            mScreenRect.set(0, 0, dw, dh);
8264        }
8265
8266        mPolicy.getContentRectLw(mTmpContentRect);
8267        displayContent.resize(mTmpContentRect);
8268
8269        int seq = mLayoutSeq+1;
8270        if (seq < 0) seq = 0;
8271        mLayoutSeq = seq;
8272
8273        boolean behindDream = false;
8274
8275        // First perform layout of any root windows (not attached
8276        // to another window).
8277        int topAttached = -1;
8278        for (i = N-1; i >= 0; i--) {
8279            final WindowState win = windows.get(i);
8280
8281            // Don't do layout of a window if it is not visible, or
8282            // soon won't be visible, to avoid wasting time and funky
8283            // changes while a window is animating away.
8284            final boolean gone = (behindDream && mPolicy.canBeForceHidden(win, win.mAttrs))
8285                    || win.isGoneForLayoutLw();
8286
8287            if (DEBUG_LAYOUT && !win.mLayoutAttached) {
8288                Slog.v(TAG, "1ST PASS " + win
8289                        + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame
8290                        + " mLayoutAttached=" + win.mLayoutAttached
8291                        + " screen changed=" + win.isConfigChanged());
8292                final AppWindowToken atoken = win.mAppToken;
8293                if (gone) Slog.v(TAG, "  GONE: mViewVisibility="
8294                        + win.mViewVisibility + " mRelayoutCalled="
8295                        + win.mRelayoutCalled + " hidden="
8296                        + win.mRootToken.hidden + " hiddenRequested="
8297                        + (atoken != null && atoken.hiddenRequested)
8298                        + " mAttachedHidden=" + win.mAttachedHidden);
8299                else Slog.v(TAG, "  VIS: mViewVisibility="
8300                        + win.mViewVisibility + " mRelayoutCalled="
8301                        + win.mRelayoutCalled + " hidden="
8302                        + win.mRootToken.hidden + " hiddenRequested="
8303                        + (atoken != null && atoken.hiddenRequested)
8304                        + " mAttachedHidden=" + win.mAttachedHidden);
8305            }
8306
8307            // If this view is GONE, then skip it -- keep the current
8308            // frame, and let the caller know so they can ignore it
8309            // if they want.  (We do the normal layout for INVISIBLE
8310            // windows, since that means "perform layout as normal,
8311            // just don't display").
8312            if (!gone || !win.mHaveFrame || win.mLayoutNeeded
8313                    || ((win.isConfigChanged() || win.setInsetsChanged()) &&
8314                            (win.mAttrs.type == TYPE_KEYGUARD ||
8315                            win.mAppToken != null && win.mAppToken.layoutConfigChanges))
8316                    || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
8317                if (!win.mLayoutAttached) {
8318                    if (initial) {
8319                        //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
8320                        win.mContentChanged = false;
8321                    }
8322                    if (win.mAttrs.type == TYPE_DREAM) {
8323                        // Don't layout windows behind a dream, so that if it
8324                        // does stuff like hide the status bar we won't get a
8325                        // bad transition when it goes away.
8326                        behindDream = true;
8327                    }
8328                    win.mLayoutNeeded = false;
8329                    win.prelayout();
8330                    mPolicy.layoutWindowLw(win, win.mAttrs, null);
8331                    win.mLayoutSeq = seq;
8332                    if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame="
8333                            + win.mFrame + " mContainingFrame="
8334                            + win.mContainingFrame + " mDisplayFrame="
8335                            + win.mDisplayFrame);
8336                } else {
8337                    if (topAttached < 0) topAttached = i;
8338                }
8339            }
8340            if (win.mViewVisibility == View.VISIBLE
8341                    && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND
8342                    && universeBackground == null) {
8343                universeBackground = win.mWinAnimator;
8344            }
8345        }
8346
8347        if (mAnimator.mUniverseBackground  != universeBackground) {
8348            mFocusMayChange = true;
8349            mAnimator.mUniverseBackground = universeBackground;
8350        }
8351
8352        boolean attachedBehindDream = false;
8353
8354        // Now perform layout of attached windows, which usually
8355        // depend on the position of the window they are attached to.
8356        // XXX does not deal with windows that are attached to windows
8357        // that are themselves attached.
8358        for (i = topAttached; i >= 0; i--) {
8359            final WindowState win = windows.get(i);
8360
8361            if (win.mLayoutAttached) {
8362                if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win
8363                        + " mHaveFrame=" + win.mHaveFrame
8364                        + " mViewVisibility=" + win.mViewVisibility
8365                        + " mRelayoutCalled=" + win.mRelayoutCalled);
8366                // If this view is GONE, then skip it -- keep the current
8367                // frame, and let the caller know so they can ignore it
8368                // if they want.  (We do the normal layout for INVISIBLE
8369                // windows, since that means "perform layout as normal,
8370                // just don't display").
8371                if (attachedBehindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) {
8372                    continue;
8373                }
8374                if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled)
8375                        || !win.mHaveFrame || win.mLayoutNeeded) {
8376                    if (initial) {
8377                        //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
8378                        win.mContentChanged = false;
8379                    }
8380                    win.mLayoutNeeded = false;
8381                    win.prelayout();
8382                    mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow);
8383                    win.mLayoutSeq = seq;
8384                    if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame="
8385                            + win.mFrame + " mContainingFrame="
8386                            + win.mContainingFrame + " mDisplayFrame="
8387                            + win.mDisplayFrame);
8388                }
8389            } else if (win.mAttrs.type == TYPE_DREAM) {
8390                // Don't layout windows behind a dream, so that if it
8391                // does stuff like hide the status bar we won't get a
8392                // bad transition when it goes away.
8393                attachedBehindDream = behindDream;
8394            }
8395        }
8396
8397        // Window frames may have changed.  Tell the input dispatcher about it.
8398        mInputMonitor.setUpdateInputWindowsNeededLw();
8399        if (updateInputWindows) {
8400            mInputMonitor.updateInputWindowsLw(false /*force*/);
8401        }
8402
8403        mPolicy.finishLayoutLw();
8404    }
8405
8406    void makeWindowFreezingScreenIfNeededLocked(WindowState w) {
8407        // If the screen is currently frozen or off, then keep
8408        // it frozen/off until this window draws at its new
8409        // orientation.
8410        if (!okToDisplay()) {
8411            if (DEBUG_ORIENTATION) Slog.v(TAG, "Changing surface while display frozen: " + w);
8412            w.mOrientationChanging = true;
8413            w.mLastFreezeDuration = 0;
8414            mInnerFields.mOrientationChangeComplete = false;
8415            if (!mWindowsFreezingScreen) {
8416                mWindowsFreezingScreen = true;
8417                // XXX should probably keep timeout from
8418                // when we first froze the display.
8419                mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
8420                mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT,
8421                        WINDOW_FREEZE_TIMEOUT_DURATION);
8422            }
8423        }
8424    }
8425
8426    /**
8427     * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
8428     * @param windows List of windows on default display.
8429     * @return bitmap indicating if another pass through layout must be made.
8430     */
8431    public int handleAppTransitionReadyLocked(WindowList windows) {
8432        int changes = 0;
8433        int i;
8434        int NN = mOpeningApps.size();
8435        boolean goodToGo = true;
8436        if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8437                "Checking " + NN + " opening apps (frozen="
8438                + mDisplayFrozen + " timeout="
8439                + mAppTransition.isTimeout() + ")...");
8440        if (!mDisplayFrozen && !mAppTransition.isTimeout()) {
8441            // If the display isn't frozen, wait to do anything until
8442            // all of the apps are ready.  Otherwise just go because
8443            // we'll unfreeze the display when everyone is ready.
8444            for (i=0; i<NN && goodToGo; i++) {
8445                AppWindowToken wtoken = mOpeningApps.get(i);
8446                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8447                        "Check opening app=" + wtoken + ": allDrawn="
8448                        + wtoken.allDrawn + " startingDisplayed="
8449                        + wtoken.startingDisplayed + " startingMoved="
8450                        + wtoken.startingMoved);
8451                if (!wtoken.allDrawn && !wtoken.startingDisplayed
8452                        && !wtoken.startingMoved) {
8453                    goodToGo = false;
8454                }
8455            }
8456        }
8457        if (goodToGo) {
8458            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO");
8459            int transit = mAppTransition.getAppTransition();
8460            if (mSkipAppTransitionAnimation) {
8461                transit = AppTransition.TRANSIT_UNSET;
8462            }
8463            mAppTransition.goodToGo();
8464            mStartingIconInTransition = false;
8465            mSkipAppTransitionAnimation = false;
8466
8467            mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
8468
8469            rebuildAppWindowListLocked();
8470
8471            // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper
8472            WindowState oldWallpaper =
8473                    mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating()
8474                        && !mWallpaperTarget.mWinAnimator.isDummyAnimation()
8475                    ? null : mWallpaperTarget;
8476
8477            mInnerFields.mWallpaperMayChange = false;
8478
8479            // The top-most window will supply the layout params,
8480            // and we will determine it below.
8481            LayoutParams animLp = null;
8482            int bestAnimLayer = -1;
8483            boolean fullscreenAnim = false;
8484
8485            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8486                    "New wallpaper target=" + mWallpaperTarget
8487                    + ", oldWallpaper=" + oldWallpaper
8488                    + ", lower target=" + mLowerWallpaperTarget
8489                    + ", upper target=" + mUpperWallpaperTarget);
8490
8491            boolean openingAppHasWallpaper = false;
8492            boolean closingAppHasWallpaper = false;
8493            final AppWindowToken lowerWallpaperAppToken;
8494            final AppWindowToken upperWallpaperAppToken;
8495            if (mLowerWallpaperTarget == null) {
8496                lowerWallpaperAppToken = upperWallpaperAppToken = null;
8497            } else {
8498                lowerWallpaperAppToken = mLowerWallpaperTarget.mAppToken;
8499                upperWallpaperAppToken = mUpperWallpaperTarget.mAppToken;
8500            }
8501
8502            // Do a first pass through the tokens for two
8503            // things:
8504            // (1) Determine if both the closing and opening
8505            // app token sets are wallpaper targets, in which
8506            // case special animations are needed
8507            // (since the wallpaper needs to stay static
8508            // behind them).
8509            // (2) Find the layout params of the top-most
8510            // application window in the tokens, which is
8511            // what will control the animation theme.
8512            final int NC = mClosingApps.size();
8513            NN = NC + mOpeningApps.size();
8514            for (i=0; i<NN; i++) {
8515                final AppWindowToken wtoken;
8516                if (i < NC) {
8517                    wtoken = mClosingApps.get(i);
8518                    if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
8519                        closingAppHasWallpaper = true;
8520                    }
8521                } else {
8522                    wtoken = mOpeningApps.get(i - NC);
8523                    if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
8524                        openingAppHasWallpaper = true;
8525                    }
8526                }
8527
8528                if (wtoken.appFullscreen) {
8529                    WindowState ws = wtoken.findMainWindow();
8530                    if (ws != null) {
8531                        animLp = ws.mAttrs;
8532                        bestAnimLayer = ws.mLayer;
8533                        fullscreenAnim = true;
8534                    }
8535                } else if (!fullscreenAnim) {
8536                    WindowState ws = wtoken.findMainWindow();
8537                    if (ws != null) {
8538                        if (ws.mLayer > bestAnimLayer) {
8539                            animLp = ws.mAttrs;
8540                            bestAnimLayer = ws.mLayer;
8541                        }
8542                    }
8543                }
8544            }
8545
8546            mAnimateWallpaperWithTarget = false;
8547            if (closingAppHasWallpaper && openingAppHasWallpaper) {
8548                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!");
8549                switch (transit) {
8550                    case AppTransition.TRANSIT_ACTIVITY_OPEN:
8551                    case AppTransition.TRANSIT_TASK_OPEN:
8552                    case AppTransition.TRANSIT_TASK_TO_FRONT:
8553                        transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN;
8554                        break;
8555                    case AppTransition.TRANSIT_ACTIVITY_CLOSE:
8556                    case AppTransition.TRANSIT_TASK_CLOSE:
8557                    case AppTransition.TRANSIT_TASK_TO_BACK:
8558                        transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE;
8559                        break;
8560                }
8561                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit: " + transit);
8562            } else if ((oldWallpaper != null) && !mOpeningApps.isEmpty()
8563                    && !mOpeningApps.contains(oldWallpaper.mAppToken)) {
8564                // We are transitioning from an activity with
8565                // a wallpaper to one without.
8566                transit = AppTransition.TRANSIT_WALLPAPER_CLOSE;
8567                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8568                        "New transit away from wallpaper: " + transit);
8569            } else if (mWallpaperTarget != null && mWallpaperTarget.isVisibleLw()) {
8570                // We are transitioning from an activity without
8571                // a wallpaper to now showing the wallpaper
8572                transit = AppTransition.TRANSIT_WALLPAPER_OPEN;
8573                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8574                        "New transit into wallpaper: " + transit);
8575            } else {
8576                mAnimateWallpaperWithTarget = true;
8577            }
8578
8579            // If all closing windows are obscured, then there is
8580            // no need to do an animation.  This is the case, for
8581            // example, when this transition is being done behind
8582            // the lock screen.
8583            if (!mPolicy.allowAppAnimationsLw()) {
8584                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8585                        "Animations disallowed by keyguard or dream.");
8586                animLp = null;
8587            }
8588
8589            AppWindowToken topOpeningApp = null;
8590            int topOpeningLayer = 0;
8591
8592            NN = mOpeningApps.size();
8593            for (i=0; i<NN; i++) {
8594                AppWindowToken wtoken = mOpeningApps.get(i);
8595                final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
8596                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken);
8597                appAnimator.clearThumbnail();
8598                wtoken.inPendingTransaction = false;
8599                appAnimator.animation = null;
8600                setTokenVisibilityLocked(wtoken, animLp, true, transit, false);
8601                wtoken.updateReportedVisibilityLocked();
8602                wtoken.waitingToShow = false;
8603
8604                appAnimator.mAllAppWinAnimators.clear();
8605                final int N = wtoken.allAppWindows.size();
8606                for (int j = 0; j < N; j++) {
8607                    appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
8608                }
8609                mAnimator.mAnimating |= appAnimator.showAllWindowsLocked();
8610
8611                if (animLp != null) {
8612                    int layer = -1;
8613                    for (int j=0; j<wtoken.windows.size(); j++) {
8614                        WindowState win = wtoken.windows.get(j);
8615                        if (win.mWinAnimator.mAnimLayer > layer) {
8616                            layer = win.mWinAnimator.mAnimLayer;
8617                        }
8618                    }
8619                    if (topOpeningApp == null || layer > topOpeningLayer) {
8620                        topOpeningApp = wtoken;
8621                        topOpeningLayer = layer;
8622                    }
8623                }
8624            }
8625            NN = mClosingApps.size();
8626            for (i=0; i<NN; i++) {
8627                AppWindowToken wtoken = mClosingApps.get(i);
8628                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken);
8629                wtoken.mAppAnimator.clearThumbnail();
8630                wtoken.inPendingTransaction = false;
8631                wtoken.mAppAnimator.animation = null;
8632                setTokenVisibilityLocked(wtoken, animLp, false, transit, false);
8633                wtoken.updateReportedVisibilityLocked();
8634                wtoken.waitingToHide = false;
8635                // Force the allDrawn flag, because we want to start
8636                // this guy's animations regardless of whether it's
8637                // gotten drawn.
8638                wtoken.allDrawn = true;
8639                wtoken.deferClearAllDrawn = false;
8640            }
8641
8642            AppWindowAnimator appAnimator =
8643                    topOpeningApp == null ? null : topOpeningApp.mAppAnimator;
8644            Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail();
8645            if (nextAppTransitionThumbnail != null && appAnimator != null
8646                    && appAnimator.animation != null) {
8647                // This thumbnail animation is very special, we need to have
8648                // an extra surface with the thumbnail included with the animation.
8649                Rect dirty = new Rect(0, 0, nextAppTransitionThumbnail.getWidth(),
8650                        nextAppTransitionThumbnail.getHeight());
8651                try {
8652                    // TODO(multi-display): support other displays
8653                    final DisplayContent displayContent = getDefaultDisplayContentLocked();
8654                    final Display display = displayContent.getDisplay();
8655                    SurfaceControl surfaceControl = new SurfaceControl(mFxSession,
8656                            "thumbnail anim",
8657                            dirty.width(), dirty.height(),
8658                            PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
8659                    surfaceControl.setLayerStack(display.getLayerStack());
8660                    appAnimator.thumbnail = surfaceControl;
8661                    if (SHOW_TRANSACTIONS) Slog.i(TAG, "  THUMBNAIL " + surfaceControl + ": CREATE");
8662                    Surface drawSurface = new Surface();
8663                    drawSurface.copyFrom(surfaceControl);
8664                    Canvas c = drawSurface.lockCanvas(dirty);
8665                    c.drawBitmap(nextAppTransitionThumbnail, 0, 0, null);
8666                    drawSurface.unlockCanvasAndPost(c);
8667                    drawSurface.release();
8668                    appAnimator.thumbnailLayer = topOpeningLayer;
8669                    DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
8670                    Animation anim = mAppTransition.createThumbnailAnimationLocked(
8671                            transit, true, true, displayInfo.appWidth, displayInfo.appHeight);
8672                    appAnimator.thumbnailAnimation = anim;
8673                    anim.restrictDuration(MAX_ANIMATION_DURATION);
8674                    anim.scaleCurrentDuration(mTransitionAnimationScale);
8675                    Point p = new Point();
8676                    mAppTransition.getStartingPoint(p);
8677                    appAnimator.thumbnailX = p.x;
8678                    appAnimator.thumbnailY = p.y;
8679                } catch (OutOfResourcesException e) {
8680                    Slog.e(TAG, "Can't allocate thumbnail/Canvas surface w=" + dirty.width()
8681                            + " h=" + dirty.height(), e);
8682                    appAnimator.clearThumbnail();
8683                }
8684            }
8685
8686            mAppTransition.postAnimationCallback();
8687            mAppTransition.clear();
8688
8689            mOpeningApps.clear();
8690            mClosingApps.clear();
8691
8692            // This has changed the visibility of windows, so perform
8693            // a new layout to get them all up-to-date.
8694            changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT
8695                    | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
8696            getDefaultDisplayContentLocked().layoutNeeded = true;
8697
8698            // TODO(multidisplay): IMEs are only supported on the default display.
8699            if (windows == getDefaultWindowListLocked()
8700                    && !moveInputMethodWindowsIfNeededLocked(true)) {
8701                assignLayersLocked(windows);
8702            }
8703            updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, false /*updateInputWindows*/);
8704            mFocusMayChange = false;
8705        }
8706
8707        return changes;
8708    }
8709
8710    /**
8711     * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
8712     * @return bitmap indicating if another pass through layout must be made.
8713     */
8714    private int handleAnimatingStoppedAndTransitionLocked() {
8715        int changes = 0;
8716
8717        mAppTransition.setIdle();
8718        // Restore window app tokens to the ActivityManager views
8719        ArrayList<TaskStack> stacks = getDefaultDisplayContentLocked().getStacks();
8720        for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
8721            final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
8722            for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
8723                final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
8724                for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
8725                    tokens.get(tokenNdx).sendingToBottom = false;
8726                }
8727            }
8728        }
8729        rebuildAppWindowListLocked();
8730
8731        changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
8732        if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
8733                "Wallpaper layer changed: assigning layers + relayout");
8734        moveInputMethodWindowsIfNeededLocked(true);
8735        mInnerFields.mWallpaperMayChange = true;
8736        // Since the window list has been rebuilt, focus might
8737        // have to be recomputed since the actual order of windows
8738        // might have changed again.
8739        mFocusMayChange = true;
8740
8741        return changes;
8742    }
8743
8744    private void updateResizingWindows(final WindowState w) {
8745        final WindowStateAnimator winAnimator = w.mWinAnimator;
8746        if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq) {
8747            w.setInsetsChanged();
8748            boolean configChanged = w.isConfigChanged();
8749            if (DEBUG_CONFIGURATION && configChanged) {
8750                Slog.v(TAG, "Win " + w + " config changed: "
8751                        + mCurConfiguration);
8752            }
8753            if (localLOGV) Slog.v(TAG, "Resizing " + w
8754                    + ": configChanged=" + configChanged
8755                    + " last=" + w.mLastFrame + " frame=" + w.mFrame);
8756            w.mLastFrame.set(w.mFrame);
8757            if (w.mContentInsetsChanged
8758                    || w.mVisibleInsetsChanged
8759                    || winAnimator.mSurfaceResized
8760                    || configChanged) {
8761                if (DEBUG_RESIZE || DEBUG_ORIENTATION) {
8762                    Slog.v(TAG, "Resize reasons for w=" + w + ": "
8763                            + " contentInsetsChanged=" + w.mContentInsetsChanged
8764                            + " " + w.mContentInsets.toShortString()
8765                            + " visibleInsetsChanged=" + w.mVisibleInsetsChanged
8766                            + " " + w.mVisibleInsets.toShortString()
8767                            + " surfaceResized=" + winAnimator.mSurfaceResized
8768                            + " configChanged=" + configChanged);
8769                }
8770
8771                w.mLastOverscanInsets.set(w.mOverscanInsets);
8772                w.mLastContentInsets.set(w.mContentInsets);
8773                w.mLastVisibleInsets.set(w.mVisibleInsets);
8774                makeWindowFreezingScreenIfNeededLocked(w);
8775                // If the orientation is changing, then we need to
8776                // hold off on unfreezing the display until this
8777                // window has been redrawn; to do that, we need
8778                // to go through the process of getting informed
8779                // by the application when it has finished drawing.
8780                if (w.mOrientationChanging) {
8781                    if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION) Slog.v(TAG,
8782                            "Orientation start waiting for draw mDrawState=DRAW_PENDING in "
8783                            + w + ", surface " + winAnimator.mSurfaceControl);
8784                    winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
8785                    if (w.mAppToken != null) {
8786                        w.mAppToken.allDrawn = false;
8787                        w.mAppToken.deferClearAllDrawn = false;
8788                    }
8789                }
8790                if (!mResizingWindows.contains(w)) {
8791                    if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
8792                            "Resizing window " + w + " to " + winAnimator.mSurfaceW
8793                            + "x" + winAnimator.mSurfaceH);
8794                    mResizingWindows.add(w);
8795                }
8796            } else if (w.mOrientationChanging) {
8797                if (w.isDrawnLw()) {
8798                    if (DEBUG_ORIENTATION) Slog.v(TAG,
8799                            "Orientation not waiting for draw in "
8800                            + w + ", surface " + winAnimator.mSurfaceControl);
8801                    w.mOrientationChanging = false;
8802                    w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
8803                            - mDisplayFreezeTime);
8804                }
8805            }
8806        }
8807    }
8808
8809    /**
8810     * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
8811     *
8812     * @param w WindowState this method is applied to.
8813     * @param currentTime The time which animations use for calculating transitions.
8814     * @param innerDw Width of app window.
8815     * @param innerDh Height of app window.
8816     */
8817    private void handleNotObscuredLocked(final WindowState w, final long currentTime,
8818                                         final int innerDw, final int innerDh) {
8819        final WindowManager.LayoutParams attrs = w.mAttrs;
8820        final int attrFlags = attrs.flags;
8821        final boolean canBeSeen = w.isDisplayedLw();
8822        final boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn();
8823
8824        if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) {
8825            // This window completely covers everything behind it,
8826            // so we want to leave all of them as undimmed (for
8827            // performance reasons).
8828            mInnerFields.mObscured = true;
8829        }
8830
8831        if (w.mHasSurface) {
8832            if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) {
8833                mInnerFields.mHoldScreen = w.mSession;
8834            }
8835            if (!mInnerFields.mSyswin && w.mAttrs.screenBrightness >= 0
8836                    && mInnerFields.mScreenBrightness < 0) {
8837                mInnerFields.mScreenBrightness = w.mAttrs.screenBrightness;
8838            }
8839            if (!mInnerFields.mSyswin && w.mAttrs.buttonBrightness >= 0
8840                    && mInnerFields.mButtonBrightness < 0) {
8841                mInnerFields.mButtonBrightness = w.mAttrs.buttonBrightness;
8842            }
8843            if (!mInnerFields.mSyswin && w.mAttrs.userActivityTimeout >= 0
8844                    && mInnerFields.mUserActivityTimeout < 0) {
8845                mInnerFields.mUserActivityTimeout = w.mAttrs.userActivityTimeout;
8846            }
8847
8848            final int type = attrs.type;
8849            if (canBeSeen
8850                    && (type == TYPE_SYSTEM_DIALOG
8851                     || type == TYPE_RECENTS_OVERLAY
8852                     || type == TYPE_KEYGUARD
8853                     || type == TYPE_SYSTEM_ERROR)) {
8854                mInnerFields.mSyswin = true;
8855            }
8856
8857            if (canBeSeen) {
8858                // This function assumes that the contents of the default display are
8859                // processed first before secondary displays.
8860                final DisplayContent displayContent = w.getDisplayContent();
8861                if (displayContent != null && displayContent.isDefaultDisplay) {
8862                    // While a dream or keyguard is showing, obscure ordinary application
8863                    // content on secondary displays (by forcibly enabling mirroring unless
8864                    // there is other content we want to show) but still allow opaque
8865                    // keyguard dialogs to be shown.
8866                    if (type == TYPE_DREAM || type == TYPE_KEYGUARD) {
8867                        mInnerFields.mObscureApplicationContentOnSecondaryDisplays = true;
8868                    }
8869                    mInnerFields.mDisplayHasContent = true;
8870                } else if (displayContent != null &&
8871                        (!mInnerFields.mObscureApplicationContentOnSecondaryDisplays
8872                        || (mInnerFields.mObscured && type == TYPE_KEYGUARD_DIALOG))) {
8873                    // Allow full screen keyguard presentation dialogs to be seen.
8874                    mInnerFields.mDisplayHasContent = true;
8875                }
8876            }
8877        }
8878    }
8879
8880    private void handleFlagDimBehind(WindowState w) {
8881        final WindowManager.LayoutParams attrs = w.mAttrs;
8882        if ((attrs.flags & FLAG_DIM_BEHIND) != 0
8883                && w.isDisplayedLw()
8884                && !w.mExiting) {
8885            final WindowStateAnimator winAnimator = w.mWinAnimator;
8886            final TaskStack stack = w.getStack();
8887            stack.setDimmingTag();
8888            if (!stack.isDimming(winAnimator)) {
8889                if (localLOGV) Slog.v(TAG, "Win " + w + " start dimming.");
8890                stack.startDimmingIfNeeded(winAnimator);
8891            }
8892        }
8893    }
8894
8895    private void updateAllDrawnLocked(DisplayContent displayContent) {
8896        // See if any windows have been drawn, so they (and others
8897        // associated with them) can now be shown.
8898        ArrayList<TaskStack> stacks = displayContent.getStacks();
8899        for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
8900            final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
8901            for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
8902                final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
8903                for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
8904                    final AppWindowToken wtoken = tokens.get(tokenNdx);
8905                    if (!wtoken.allDrawn) {
8906                        int numInteresting = wtoken.numInterestingWindows;
8907                        if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
8908                            if (DEBUG_VISIBILITY) Slog.v(TAG,
8909                                    "allDrawn: " + wtoken
8910                                    + " interesting=" + numInteresting
8911                                    + " drawn=" + wtoken.numDrawnWindows);
8912                            wtoken.allDrawn = true;
8913                            mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, wtoken.token).sendToTarget();
8914                        }
8915                    }
8916                }
8917            }
8918        }
8919    }
8920
8921    // "Something has changed!  Let's make it correct now."
8922    private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) {
8923        if (DEBUG_WINDOW_TRACE) {
8924            Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by "
8925                    + Debug.getCallers(3));
8926        }
8927
8928        final long currentTime = SystemClock.uptimeMillis();
8929
8930        int i;
8931
8932        if (mFocusMayChange) {
8933            mFocusMayChange = false;
8934            updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
8935                    false /*updateInputWindows*/);
8936        }
8937
8938        // Initialize state of exiting tokens.
8939        final int numDisplays = mDisplayContents.size();
8940        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
8941            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
8942            for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) {
8943                displayContent.mExitingTokens.get(i).hasVisible = false;
8944            }
8945        }
8946
8947        for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
8948            // Initialize state of exiting applications.
8949            final AppTokenList exitingAppTokens =
8950                    mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
8951            for (int tokenNdx = exitingAppTokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
8952                exitingAppTokens.get(tokenNdx).hasVisible = false;
8953            }
8954        }
8955
8956        mInnerFields.mHoldScreen = null;
8957        mInnerFields.mScreenBrightness = -1;
8958        mInnerFields.mButtonBrightness = -1;
8959        mInnerFields.mUserActivityTimeout = -1;
8960        mInnerFields.mObscureApplicationContentOnSecondaryDisplays = false;
8961
8962        mTransactionSequence++;
8963
8964        final DisplayContent defaultDisplay = getDefaultDisplayContentLocked();
8965        final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo();
8966        final int defaultDw = defaultInfo.logicalWidth;
8967        final int defaultDh = defaultInfo.logicalHeight;
8968
8969        if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
8970                ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
8971        SurfaceControl.openTransaction();
8972        try {
8973
8974            if (mWatermark != null) {
8975                mWatermark.positionSurface(defaultDw, defaultDh);
8976            }
8977            if (mStrictModeFlash != null) {
8978                mStrictModeFlash.positionSurface(defaultDw, defaultDh);
8979            }
8980
8981            boolean focusDisplayed = false;
8982
8983            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
8984                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
8985                boolean updateAllDrawn = false;
8986                WindowList windows = displayContent.getWindowList();
8987                DisplayInfo displayInfo = displayContent.getDisplayInfo();
8988                final int displayId = displayContent.getDisplayId();
8989                final int dw = displayInfo.logicalWidth;
8990                final int dh = displayInfo.logicalHeight;
8991                final int innerDw = displayInfo.appWidth;
8992                final int innerDh = displayInfo.appHeight;
8993                final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
8994
8995                // Reset for each display.
8996                mInnerFields.mDisplayHasContent = false;
8997
8998                int repeats = 0;
8999                do {
9000                    repeats++;
9001                    if (repeats > 6) {
9002                        Slog.w(TAG, "Animation repeat aborted after too many iterations");
9003                        displayContent.layoutNeeded = false;
9004                        break;
9005                    }
9006
9007                    if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner",
9008                        displayContent.pendingLayoutChanges);
9009
9010                    if ((displayContent.pendingLayoutChanges &
9011                            WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0 &&
9012                            (adjustWallpaperWindowsLocked() &
9013                                    ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
9014                        assignLayersLocked(windows);
9015                        displayContent.layoutNeeded = true;
9016                    }
9017
9018                    if (isDefaultDisplay && (displayContent.pendingLayoutChanges
9019                            & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
9020                        if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
9021                        if (updateOrientationFromAppTokensLocked(true)) {
9022                            displayContent.layoutNeeded = true;
9023                            mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
9024                        }
9025                    }
9026
9027                    if ((displayContent.pendingLayoutChanges
9028                            & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
9029                        displayContent.layoutNeeded = true;
9030                    }
9031
9032                    // FIRST LOOP: Perform a layout, if needed.
9033                    if (repeats < 4) {
9034                        performLayoutLockedInner(displayContent, repeats == 1,
9035                                false /*updateInputWindows*/);
9036                    } else {
9037                        Slog.w(TAG, "Layout repeat skipped after too many iterations");
9038                    }
9039
9040                    // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think
9041                    // it is animating.
9042                    displayContent.pendingLayoutChanges = 0;
9043
9044                    if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number "
9045                            + mLayoutRepeatCount, displayContent.pendingLayoutChanges);
9046
9047                    if (isDefaultDisplay) {
9048                        mPolicy.beginPostLayoutPolicyLw(dw, dh);
9049                        for (i = windows.size() - 1; i >= 0; i--) {
9050                            WindowState w = windows.get(i);
9051                            if (w.mHasSurface) {
9052                                mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs);
9053                            }
9054                        }
9055                        displayContent.pendingLayoutChanges |= mPolicy.finishPostLayoutPolicyLw();
9056                        if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats(
9057                            "after finishPostLayoutPolicyLw", displayContent.pendingLayoutChanges);
9058                    }
9059                } while (displayContent.pendingLayoutChanges != 0);
9060
9061                mInnerFields.mObscured = false;
9062                mInnerFields.mSyswin = false;
9063                displayContent.resetDimming();
9064
9065                // Only used if default window
9066                final boolean someoneLosingFocus = !mLosingFocus.isEmpty();
9067
9068                final int N = windows.size();
9069                for (i=N-1; i>=0; i--) {
9070                    WindowState w = windows.get(i);
9071                    final TaskStack stack = w.getStack();
9072                    if (stack == null) {
9073                        continue;
9074                    }
9075
9076                    final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured;
9077
9078                    // Update effect.
9079                    w.mObscured = mInnerFields.mObscured;
9080                    if (!mInnerFields.mObscured) {
9081                        handleNotObscuredLocked(w, currentTime, innerDw, innerDh);
9082                    }
9083
9084                    if (!stack.testDimmingTag()) {
9085                        handleFlagDimBehind(w);
9086                    }
9087
9088                    if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w)
9089                            && w.isVisibleLw()) {
9090                        // This is the wallpaper target and its obscured state
9091                        // changed... make sure the current wallaper's visibility
9092                        // has been updated accordingly.
9093                        updateWallpaperVisibilityLocked();
9094                    }
9095
9096                    final WindowStateAnimator winAnimator = w.mWinAnimator;
9097
9098                    // If the window has moved due to its containing
9099                    // content frame changing, then we'd like to animate
9100                    // it.
9101                    if (w.mHasSurface && w.shouldAnimateMove()) {
9102                        // Frame has moved, containing content frame
9103                        // has also moved, and we're not currently animating...
9104                        // let's do something.
9105                        Animation a = AnimationUtils.loadAnimation(mContext,
9106                                com.android.internal.R.anim.window_move_from_decor);
9107                        winAnimator.setAnimation(a);
9108                        winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left;
9109                        winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top;
9110                        try {
9111                            w.mClient.moved(w.mFrame.left, w.mFrame.top);
9112                        } catch (RemoteException e) {
9113                        }
9114                    }
9115
9116                    //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
9117                    w.mContentChanged = false;
9118
9119                    // Moved from updateWindowsAndWallpaperLocked().
9120                    if (w.mHasSurface) {
9121                        // Take care of the window being ready to display.
9122                        final boolean committed =
9123                                winAnimator.commitFinishDrawingLocked(currentTime);
9124                        if (isDefaultDisplay && committed) {
9125                            if (w.mAttrs.type == TYPE_DREAM) {
9126                                // HACK: When a dream is shown, it may at that
9127                                // point hide the lock screen.  So we need to
9128                                // redo the layout to let the phone window manager
9129                                // make this happen.
9130                                displayContent.pendingLayoutChanges |=
9131                                        WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9132                                if (DEBUG_LAYOUT_REPEATS) {
9133                                    debugLayoutRepeats(
9134                                        "dream and commitFinishDrawingLocked true",
9135                                        displayContent.pendingLayoutChanges);
9136                                }
9137                            }
9138                            if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
9139                                if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
9140                                        "First draw done in potential wallpaper target " + w);
9141                                mInnerFields.mWallpaperMayChange = true;
9142                                displayContent.pendingLayoutChanges |=
9143                                        WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
9144                                if (DEBUG_LAYOUT_REPEATS) {
9145                                    debugLayoutRepeats(
9146                                        "wallpaper and commitFinishDrawingLocked true",
9147                                        displayContent.pendingLayoutChanges);
9148                                }
9149                            }
9150                        }
9151
9152                        winAnimator.setSurfaceBoundariesLocked(recoveringMemory);
9153
9154                        final AppWindowToken atoken = w.mAppToken;
9155                        if (DEBUG_STARTING_WINDOW && atoken != null
9156                                && w == atoken.startingWindow) {
9157                            Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen="
9158                                + w.isOnScreen() + " allDrawn=" + atoken.allDrawn
9159                                + " freezingScreen=" + atoken.mAppAnimator.freezingScreen);
9160                        }
9161                        if (atoken != null
9162                                && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) {
9163                            if (atoken.lastTransactionSequence != mTransactionSequence) {
9164                                atoken.lastTransactionSequence = mTransactionSequence;
9165                                atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
9166                                atoken.startingDisplayed = false;
9167                            }
9168                            if ((w.isOnScreen() || winAnimator.mAttrType == TYPE_BASE_APPLICATION)
9169                                    && !w.mExiting && !w.mDestroying) {
9170                                if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
9171                                    Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
9172                                            + ", isAnimating=" + winAnimator.isAnimating());
9173                                    if (!w.isDrawnLw()) {
9174                                        Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceControl
9175                                                + " pv=" + w.mPolicyVisibility
9176                                                + " mDrawState=" + winAnimator.mDrawState
9177                                                + " ah=" + w.mAttachedHidden
9178                                                + " th=" + atoken.hiddenRequested
9179                                                + " a=" + winAnimator.mAnimating);
9180                                    }
9181                                }
9182                                if (w != atoken.startingWindow) {
9183                                    if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) {
9184                                        atoken.numInterestingWindows++;
9185                                        if (w.isDrawnLw()) {
9186                                            atoken.numDrawnWindows++;
9187                                            if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG,
9188                                                    "tokenMayBeDrawn: " + atoken
9189                                                    + " freezingScreen=" + atoken.mAppAnimator.freezingScreen
9190                                                    + " mAppFreezing=" + w.mAppFreezing);
9191                                            updateAllDrawn = true;
9192                                        }
9193                                    }
9194                                } else if (w.isDrawnLw()) {
9195                                    atoken.startingDisplayed = true;
9196                                }
9197                            }
9198                        }
9199                    }
9200
9201                    if (isDefaultDisplay && someoneLosingFocus && (w == mCurrentFocus)
9202                            && w.isDisplayedLw()) {
9203                        focusDisplayed = true;
9204                    }
9205
9206                    updateResizingWindows(w);
9207                }
9208
9209                mDisplayManagerInternal.setDisplayHasContent(displayId,
9210                        mInnerFields.mDisplayHasContent,
9211                        true /* inTraversal, must call performTraversalInTrans... below */);
9212
9213                getDisplayContentLocked(displayId).stopDimmingIfNeeded();
9214
9215                if (updateAllDrawn) {
9216                    updateAllDrawnLocked(displayContent);
9217                }
9218            }
9219
9220            if (focusDisplayed) {
9221                mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS);
9222            }
9223
9224            // Give the display manager a chance to adjust properties
9225            // like display rotation if it needs to.
9226            mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
9227
9228        } catch (RuntimeException e) {
9229            Log.wtf(TAG, "Unhandled exception in Window Manager", e);
9230        } finally {
9231            SurfaceControl.closeTransaction();
9232            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
9233                    "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
9234        }
9235
9236        final WindowList defaultWindows = defaultDisplay.getWindowList();
9237
9238        // If we are ready to perform an app transition, check through
9239        // all of the app tokens to be shown and see if they are ready
9240        // to go.
9241        if (mAppTransition.isReady()) {
9242            defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows);
9243            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked",
9244                    defaultDisplay.pendingLayoutChanges);
9245        }
9246
9247        if (!mAnimator.mAnimating && mAppTransition.isRunning()) {
9248            // We have finished the animation of an app transition.  To do
9249            // this, we have delayed a lot of operations like showing and
9250            // hiding apps, moving apps in Z-order, etc.  The app token list
9251            // reflects the correct Z-order, but the window list may now
9252            // be out of sync with it.  So here we will just rebuild the
9253            // entire app window list.  Fun!
9254            defaultDisplay.pendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked();
9255            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock",
9256                defaultDisplay.pendingLayoutChanges);
9257        }
9258
9259        if (mInnerFields.mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0
9260                && !mAppTransition.isReady()) {
9261            // At this point, there was a window with a wallpaper that
9262            // was force hiding other windows behind it, but now it
9263            // is going away.  This may be simple -- just animate
9264            // away the wallpaper and its window -- or it may be
9265            // hard -- the wallpaper now needs to be shown behind
9266            // something that was hidden.
9267            defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9268            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked",
9269                defaultDisplay.pendingLayoutChanges);
9270        }
9271        mInnerFields.mWallpaperForceHidingChanged = false;
9272
9273        if (mInnerFields.mWallpaperMayChange) {
9274            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Wallpaper may change!  Adjusting");
9275            defaultDisplay.pendingLayoutChanges |=
9276                    WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
9277            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("WallpaperMayChange",
9278                    defaultDisplay.pendingLayoutChanges);
9279        }
9280
9281        if (mFocusMayChange) {
9282            mFocusMayChange = false;
9283            if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
9284                    false /*updateInputWindows*/)) {
9285                defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
9286            }
9287        }
9288
9289        if (needsLayout()) {
9290            defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9291            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded",
9292                    defaultDisplay.pendingLayoutChanges);
9293        }
9294
9295        for (i = mResizingWindows.size() - 1; i >= 0; i--) {
9296            WindowState win = mResizingWindows.get(i);
9297            if (win.mAppFreezing) {
9298                // Don't remove this window until rotation has completed.
9299                continue;
9300            }
9301            final WindowStateAnimator winAnimator = win.mWinAnimator;
9302            if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
9303                    "Reporting new frame to " + win + ": " + win.mCompatFrame);
9304            int diff = 0;
9305            boolean configChanged = win.isConfigChanged();
9306            if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION)
9307                    && configChanged) {
9308                Slog.i(TAG, "Sending new config to window " + win + ": "
9309                        + winAnimator.mSurfaceW + "x" + winAnimator.mSurfaceH
9310                        + " / " + mCurConfiguration + " / 0x"
9311                        + Integer.toHexString(diff));
9312            }
9313            win.setConfiguration(mCurConfiguration);
9314            if (DEBUG_ORIENTATION &&
9315                    winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING) Slog.i(
9316                    TAG, "Resizing " + win + " WITH DRAW PENDING");
9317            win.reportResized();
9318            mResizingWindows.remove(i);
9319        }
9320
9321        if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG,
9322                "With display frozen, orientationChangeComplete="
9323                + mInnerFields.mOrientationChangeComplete);
9324        if (mInnerFields.mOrientationChangeComplete) {
9325            if (mWindowsFreezingScreen) {
9326                mWindowsFreezingScreen = false;
9327                mLastFinishedFreezeSource = mInnerFields.mLastWindowFreezeSource;
9328                mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
9329            }
9330            stopFreezingDisplayLocked();
9331        }
9332
9333        // Destroy the surface of any windows that are no longer visible.
9334        boolean wallpaperDestroyed = false;
9335        i = mDestroySurface.size();
9336        if (i > 0) {
9337            do {
9338                i--;
9339                WindowState win = mDestroySurface.get(i);
9340                win.mDestroying = false;
9341                if (mInputMethodWindow == win) {
9342                    mInputMethodWindow = null;
9343                }
9344                if (win == mWallpaperTarget) {
9345                    wallpaperDestroyed = true;
9346                }
9347                win.mWinAnimator.destroySurfaceLocked();
9348            } while (i > 0);
9349            mDestroySurface.clear();
9350        }
9351
9352        // Time to remove any exiting tokens?
9353        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9354            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9355            ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens;
9356            for (i = exitingTokens.size() - 1; i >= 0; i--) {
9357                WindowToken token = exitingTokens.get(i);
9358                if (!token.hasVisible) {
9359                    exitingTokens.remove(i);
9360                    if (token.windowType == TYPE_WALLPAPER) {
9361                        mWallpaperTokens.remove(token);
9362                    }
9363                }
9364            }
9365        }
9366
9367        // Time to remove any exiting applications?
9368        for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
9369            // Initialize state of exiting applications.
9370            final AppTokenList exitingAppTokens =
9371                    mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
9372            for (i = exitingAppTokens.size() - 1; i >= 0; i--) {
9373                AppWindowToken token = exitingAppTokens.get(i);
9374                if (!token.hasVisible && !mClosingApps.contains(token)) {
9375                    // Make sure there is no animation running on this token,
9376                    // so any windows associated with it will be removed as
9377                    // soon as their animations are complete
9378                    token.mAppAnimator.clearAnimation();
9379                    token.mAppAnimator.animating = false;
9380                    if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
9381                            "performLayout: App token exiting now removed" + token);
9382                    removeAppFromTask(token);
9383                    exitingAppTokens.remove(i);
9384                }
9385            }
9386        }
9387
9388        if (!mAnimator.mAnimating && mRelayoutWhileAnimating.size() > 0) {
9389            for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) {
9390                try {
9391                    mRelayoutWhileAnimating.get(j).mClient.doneAnimating();
9392                } catch (RemoteException e) {
9393                }
9394            }
9395            mRelayoutWhileAnimating.clear();
9396        }
9397
9398        if (wallpaperDestroyed) {
9399            defaultDisplay.pendingLayoutChanges |=
9400                    WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
9401            defaultDisplay.layoutNeeded = true;
9402        }
9403
9404        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9405            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9406            if (displayContent.pendingLayoutChanges != 0) {
9407                displayContent.layoutNeeded = true;
9408            }
9409        }
9410
9411        // Finally update all input windows now that the window changes have stabilized.
9412        mInputMonitor.updateInputWindowsLw(true /*force*/);
9413
9414        setHoldScreenLocked(mInnerFields.mHoldScreen);
9415        if (!mDisplayFrozen) {
9416            if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) {
9417                mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(-1);
9418            } else {
9419                mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(
9420                        toBrightnessOverride(mInnerFields.mScreenBrightness));
9421            }
9422            if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) {
9423                mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(-1);
9424            } else {
9425                mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(
9426                        toBrightnessOverride(mInnerFields.mButtonBrightness));
9427            }
9428            mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager(
9429                    mInnerFields.mUserActivityTimeout);
9430        }
9431
9432        if (mTurnOnScreen) {
9433            if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!");
9434            mPowerManager.wakeUp(SystemClock.uptimeMillis());
9435            mTurnOnScreen = false;
9436        }
9437
9438        if (mInnerFields.mUpdateRotation) {
9439            if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
9440            if (updateRotationUncheckedLocked(false)) {
9441                mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
9442            } else {
9443                mInnerFields.mUpdateRotation = false;
9444            }
9445        }
9446
9447        if (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded
9448                && !mInnerFields.mUpdateRotation) {
9449            checkDrawnWindowsLocked();
9450        }
9451
9452        final int N = mPendingRemove.size();
9453        if (N > 0) {
9454            if (mPendingRemoveTmp.length < N) {
9455                mPendingRemoveTmp = new WindowState[N+10];
9456            }
9457            mPendingRemove.toArray(mPendingRemoveTmp);
9458            mPendingRemove.clear();
9459            DisplayContentList displayList = new DisplayContentList();
9460            for (i = 0; i < N; i++) {
9461                WindowState w = mPendingRemoveTmp[i];
9462                removeWindowInnerLocked(w.mSession, w);
9463                final DisplayContent displayContent = w.getDisplayContent();
9464                if (displayContent != null && !displayList.contains(displayContent)) {
9465                    displayList.add(displayContent);
9466                }
9467            }
9468
9469            for (DisplayContent displayContent : displayList) {
9470                assignLayersLocked(displayContent.getWindowList());
9471                displayContent.layoutNeeded = true;
9472            }
9473        }
9474
9475        setFocusedStackFrame();
9476
9477        // Check to see if we are now in a state where the screen should
9478        // be enabled, because the window obscured flags have changed.
9479        enableScreenIfNeededLocked();
9480
9481        scheduleAnimationLocked();
9482
9483        if (DEBUG_WINDOW_TRACE) {
9484            Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: animating="
9485                    + mAnimator.mAnimating);
9486        }
9487    }
9488
9489    private int toBrightnessOverride(float value) {
9490        return (int)(value * PowerManager.BRIGHTNESS_ON);
9491    }
9492
9493    void checkDrawnWindowsLocked() {
9494        if (mWaitingForDrawn.size() > 0) {
9495            for (int j=mWaitingForDrawn.size()-1; j>=0; j--) {
9496                Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(j);
9497                WindowState win = pair.first;
9498                //Slog.i(TAG, "Waiting for drawn " + win + ": removed="
9499                //        + win.mRemoved + " visible=" + win.isVisibleLw()
9500                //        + " shown=" + win.mSurfaceShown);
9501                if (win.mRemoved) {
9502                    // Window has been removed; no draw will now happen, so stop waiting.
9503                    Slog.w(TAG, "Aborted waiting for drawn: " + pair.first);
9504                    try {
9505                        pair.second.sendResult(null);
9506                    } catch (RemoteException e) {
9507                    }
9508                    mWaitingForDrawn.remove(pair);
9509                    mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
9510                } else if (win.mWinAnimator.mSurfaceShown) {
9511                    // Window is now drawn (and shown).
9512                    try {
9513                        pair.second.sendResult(null);
9514                    } catch (RemoteException e) {
9515                    }
9516                    mWaitingForDrawn.remove(pair);
9517                    mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
9518                }
9519            }
9520        }
9521    }
9522
9523    @Override
9524    public boolean waitForWindowDrawn(IBinder token, IRemoteCallback callback) {
9525        if (token != null && callback != null) {
9526            synchronized (mWindowMap) {
9527                WindowState win = windowForClientLocked(null, token, true);
9528                if (win != null) {
9529                    Pair<WindowState, IRemoteCallback> pair =
9530                            new Pair<WindowState, IRemoteCallback>(win, callback);
9531                    Message m = mH.obtainMessage(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
9532                    mH.sendMessageDelayed(m, 2000);
9533                    mWaitingForDrawn.add(pair);
9534                    checkDrawnWindowsLocked();
9535                    return true;
9536                }
9537                Slog.i(TAG, "waitForWindowDrawn: win null");
9538            }
9539        }
9540        return false;
9541    }
9542
9543    void setHoldScreenLocked(final Session newHoldScreen) {
9544        final boolean hold = newHoldScreen != null;
9545
9546        if (hold && mHoldingScreenOn != newHoldScreen) {
9547            mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid));
9548        }
9549        mHoldingScreenOn = newHoldScreen;
9550
9551        final boolean state = mHoldingScreenWakeLock.isHeld();
9552        if (hold != state) {
9553            if (hold) {
9554                mHoldingScreenWakeLock.acquire();
9555                mPolicy.keepScreenOnStartedLw();
9556            } else {
9557                mPolicy.keepScreenOnStoppedLw();
9558                mHoldingScreenWakeLock.release();
9559            }
9560        }
9561    }
9562
9563    void requestTraversal() {
9564        synchronized (mWindowMap) {
9565            requestTraversalLocked();
9566        }
9567    }
9568
9569    void requestTraversalLocked() {
9570        if (!mTraversalScheduled) {
9571            mTraversalScheduled = true;
9572            mH.sendEmptyMessage(H.DO_TRAVERSAL);
9573        }
9574    }
9575
9576    /** Note that Locked in this case is on mLayoutToAnim */
9577    void scheduleAnimationLocked() {
9578        if (!mAnimationScheduled) {
9579            mAnimationScheduled = true;
9580            mChoreographer.postCallback(
9581                    Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null);
9582        }
9583    }
9584
9585    private boolean needsLayout() {
9586        final int numDisplays = mDisplayContents.size();
9587        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9588            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9589            if (displayContent.layoutNeeded) {
9590                return true;
9591            }
9592        }
9593        return false;
9594    }
9595
9596    boolean copyAnimToLayoutParamsLocked() {
9597        boolean doRequest = false;
9598
9599        final int bulkUpdateParams = mAnimator.mBulkUpdateParams;
9600        if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) {
9601            mInnerFields.mUpdateRotation = true;
9602            doRequest = true;
9603        }
9604        if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) {
9605            mInnerFields.mWallpaperMayChange = true;
9606            doRequest = true;
9607        }
9608        if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) {
9609            mInnerFields.mWallpaperForceHidingChanged = true;
9610            doRequest = true;
9611        }
9612        if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) == 0) {
9613            mInnerFields.mOrientationChangeComplete = false;
9614        } else {
9615            mInnerFields.mOrientationChangeComplete = true;
9616            mInnerFields.mLastWindowFreezeSource = mAnimator.mLastWindowFreezeSource;
9617            if (mWindowsFreezingScreen) {
9618                doRequest = true;
9619            }
9620        }
9621        if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) {
9622            mTurnOnScreen = true;
9623        }
9624        if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_ACTION_PENDING) != 0) {
9625            mInnerFields.mWallpaperActionPending = true;
9626        }
9627
9628        return doRequest;
9629    }
9630
9631    /** If a window that has an animation specifying a colored background and the current wallpaper
9632     * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to
9633     * suddenly disappear. */
9634    int adjustAnimationBackground(WindowStateAnimator winAnimator) {
9635        WindowList windows = winAnimator.mWin.getWindowList();
9636        for (int i = windows.size() - 1; i >= 0; --i) {
9637            WindowState testWin = windows.get(i);
9638            if (testWin.mIsWallpaper && testWin.isVisibleNow()) {
9639                return testWin.mWinAnimator.mAnimLayer;
9640            }
9641        }
9642        return winAnimator.mAnimLayer;
9643    }
9644
9645    boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation,
9646                                           boolean secure) {
9647        final SurfaceControl surface = winAnimator.mSurfaceControl;
9648        boolean leakedSurface = false;
9649        boolean killedApps = false;
9650
9651        EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(),
9652                winAnimator.mSession.mPid, operation);
9653
9654        if (mForceRemoves == null) {
9655            mForceRemoves = new ArrayList<WindowState>();
9656        }
9657
9658        long callingIdentity = Binder.clearCallingIdentity();
9659        try {
9660            // There was some problem...   first, do a sanity check of the
9661            // window list to make sure we haven't left any dangling surfaces
9662            // around.
9663
9664            Slog.i(TAG, "Out of memory for surface!  Looking for leaks...");
9665            final int numDisplays = mDisplayContents.size();
9666            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9667                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
9668                final int numWindows = windows.size();
9669                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
9670                    final WindowState ws = windows.get(winNdx);
9671                    WindowStateAnimator wsa = ws.mWinAnimator;
9672                    if (wsa.mSurfaceControl != null) {
9673                        if (!mSessions.contains(wsa.mSession)) {
9674                            Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): "
9675                                    + ws + " surface=" + wsa.mSurfaceControl
9676                                    + " token=" + ws.mToken
9677                                    + " pid=" + ws.mSession.mPid
9678                                    + " uid=" + ws.mSession.mUid);
9679                            if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null);
9680                            wsa.mSurfaceControl.destroy();
9681                            wsa.mSurfaceShown = false;
9682                            wsa.mSurfaceControl = null;
9683                            ws.mHasSurface = false;
9684                            mForceRemoves.add(ws);
9685                            leakedSurface = true;
9686                        } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) {
9687                            Slog.w(TAG, "LEAKED SURFACE (app token hidden): "
9688                                    + ws + " surface=" + wsa.mSurfaceControl
9689                                    + " token=" + ws.mAppToken);
9690                            if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null);
9691                            wsa.mSurfaceControl.destroy();
9692                            wsa.mSurfaceShown = false;
9693                            wsa.mSurfaceControl = null;
9694                            ws.mHasSurface = false;
9695                            leakedSurface = true;
9696                        }
9697                    }
9698                }
9699            }
9700
9701            if (!leakedSurface) {
9702                Slog.w(TAG, "No leaked surfaces; killing applicatons!");
9703                SparseIntArray pidCandidates = new SparseIntArray();
9704                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9705                    final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
9706                    final int numWindows = windows.size();
9707                    for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
9708                        final WindowState ws = windows.get(winNdx);
9709                        if (mForceRemoves.contains(ws)) {
9710                            continue;
9711                        }
9712                        WindowStateAnimator wsa = ws.mWinAnimator;
9713                        if (wsa.mSurfaceControl != null) {
9714                            pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid);
9715                        }
9716                    }
9717                    if (pidCandidates.size() > 0) {
9718                        int[] pids = new int[pidCandidates.size()];
9719                        for (int i=0; i<pids.length; i++) {
9720                            pids[i] = pidCandidates.keyAt(i);
9721                        }
9722                        try {
9723                            if (mActivityManager.killPids(pids, "Free memory", secure)) {
9724                                killedApps = true;
9725                            }
9726                        } catch (RemoteException e) {
9727                        }
9728                    }
9729                }
9730            }
9731
9732            if (leakedSurface || killedApps) {
9733                // We managed to reclaim some memory, so get rid of the trouble
9734                // surface and ask the app to request another one.
9735                Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry.");
9736                if (surface != null) {
9737                    if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin,
9738                            "RECOVER DESTROY", null);
9739                    surface.destroy();
9740                    winAnimator.mSurfaceShown = false;
9741                    winAnimator.mSurfaceControl = null;
9742                    winAnimator.mWin.mHasSurface = false;
9743                    scheduleRemoveStartingWindow(winAnimator.mWin.mAppToken);
9744                }
9745
9746                try {
9747                    winAnimator.mWin.mClient.dispatchGetNewSurface();
9748                } catch (RemoteException e) {
9749                }
9750            }
9751        } finally {
9752            Binder.restoreCallingIdentity(callingIdentity);
9753        }
9754
9755        return leakedSurface || killedApps;
9756    }
9757
9758    private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
9759        WindowState newFocus = computeFocusedWindowLocked();
9760        if (mCurrentFocus != newFocus) {
9761            Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus");
9762            // This check makes sure that we don't already have the focus
9763            // change message pending.
9764            mH.removeMessages(H.REPORT_FOCUS_CHANGE);
9765            mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
9766            // TODO(multidisplay): Focused windows on default display only.
9767            final DisplayContent displayContent = getDefaultDisplayContentLocked();
9768            final boolean imWindowChanged = moveInputMethodWindowsIfNeededLocked(
9769                    mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS
9770                            && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES);
9771            if (imWindowChanged) {
9772                displayContent.layoutNeeded = true;
9773                newFocus = computeFocusedWindowLocked();
9774            }
9775
9776            if (DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG, "Changing focus from " +
9777                    mCurrentFocus + " to " + newFocus + " Callers=" + Debug.getCallers(4));
9778            final WindowState oldFocus = mCurrentFocus;
9779            mCurrentFocus = newFocus;
9780            mLosingFocus.remove(newFocus);
9781            int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
9782
9783            if (imWindowChanged && oldFocus != mInputMethodWindow) {
9784                // Focus of the input method window changed. Perform layout if needed.
9785                if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
9786                    performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows);
9787                    focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9788                } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
9789                    // Client will do the layout, but we need to assign layers
9790                    // for handleNewWindowLocked() below.
9791                    assignLayersLocked(displayContent.getWindowList());
9792                }
9793            }
9794
9795            if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
9796                // The change in focus caused us to need to do a layout.  Okay.
9797                displayContent.layoutNeeded = true;
9798                if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
9799                    performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows);
9800                }
9801            }
9802
9803            if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
9804                // If we defer assigning layers, then the caller is responsible for
9805                // doing this part.
9806                finishUpdateFocusedWindowAfterAssignLayersLocked(updateInputWindows);
9807            }
9808
9809            Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
9810            return true;
9811        }
9812        return false;
9813    }
9814
9815    private void finishUpdateFocusedWindowAfterAssignLayersLocked(boolean updateInputWindows) {
9816        mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows);
9817    }
9818
9819    private WindowState computeFocusedWindowLocked() {
9820        if (mAnimator.mUniverseBackground != null
9821                && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) {
9822            return mAnimator.mUniverseBackground.mWin;
9823        }
9824
9825        final int displayCount = mDisplayContents.size();
9826        for (int i = 0; i < displayCount; i++) {
9827            final DisplayContent displayContent = mDisplayContents.valueAt(i);
9828            WindowState win = findFocusedWindowLocked(displayContent);
9829            if (win != null) {
9830                return win;
9831            }
9832        }
9833        return null;
9834    }
9835
9836    private WindowState findFocusedWindowLocked(DisplayContent displayContent) {
9837        final WindowList windows = displayContent.getWindowList();
9838        for (int i = windows.size() - 1; i >= 0; i--) {
9839            final WindowState win = windows.get(i);
9840
9841            if (localLOGV || DEBUG_FOCUS) Slog.v(
9842                TAG, "Looking for focus: " + i
9843                + " = " + win
9844                + ", flags=" + win.mAttrs.flags
9845                + ", canReceive=" + win.canReceiveKeys());
9846
9847            AppWindowToken wtoken = win.mAppToken;
9848
9849            // If this window's application has been removed, just skip it.
9850            if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) {
9851                if (DEBUG_FOCUS) Slog.v(TAG, "Skipping " + wtoken + " because "
9852                        + (wtoken.removed ? "removed" : "sendingToBottom"));
9853                continue;
9854            }
9855
9856            if (!win.canReceiveKeys()) {
9857                continue;
9858            }
9859
9860            // Descend through all of the app tokens and find the first that either matches
9861            // win.mAppToken (return win) or mFocusedApp (return null).
9862            if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING &&
9863                    mFocusedApp != null) {
9864                ArrayList<Task> tasks = displayContent.getTasks();
9865                for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
9866                    AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
9867                    int tokenNdx = tokens.size() - 1;
9868                    for ( ; tokenNdx >= 0; --tokenNdx) {
9869                        final AppWindowToken token = tokens.get(tokenNdx);
9870                        if (wtoken == token) {
9871                            break;
9872                        }
9873                        if (mFocusedApp == token) {
9874                            // Whoops, we are below the focused app...  no focus for you!
9875                            if (localLOGV || DEBUG_FOCUS_LIGHT) Slog.v(TAG,
9876                                    "findFocusedWindow: Reached focused app=" + mFocusedApp);
9877                            return null;
9878                        }
9879                    }
9880                    if (tokenNdx >= 0) {
9881                        // Early exit from loop, must have found the matching token.
9882                        break;
9883                    }
9884                }
9885            }
9886
9887            if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: Found new focus @ " + i +
9888                        " = " + win);
9889            return win;
9890        }
9891
9892        if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: No focusable windows.");
9893        return null;
9894    }
9895
9896    private void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) {
9897        if (mDisplayFrozen) {
9898            return;
9899        }
9900
9901        if (!mDisplayReady || !mPolicy.isScreenOnFully()) {
9902            // No need to freeze the screen before the system is ready or if
9903            // the screen is off.
9904            return;
9905        }
9906
9907        mScreenFrozenLock.acquire();
9908
9909        mDisplayFrozen = true;
9910        mDisplayFreezeTime = SystemClock.elapsedRealtime();
9911        mLastFinishedFreezeSource = null;
9912
9913        mInputMonitor.freezeInputDispatchingLw();
9914
9915        // Clear the last input window -- that is just used for
9916        // clean transitions between IMEs, and if we are freezing
9917        // the screen then the whole world is changing behind the scenes.
9918        mPolicy.setLastInputMethodWindowLw(null, null);
9919
9920        if (mAppTransition.isTransitionSet()) {
9921            mAppTransition.freeze();
9922        }
9923
9924        if (PROFILE_ORIENTATION) {
9925            File file = new File("/data/system/frozen");
9926            Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
9927        }
9928
9929        if (CUSTOM_SCREEN_ROTATION) {
9930            mExitAnimId = exitAnim;
9931            mEnterAnimId = enterAnim;
9932            final DisplayContent displayContent = getDefaultDisplayContentLocked();
9933            final int displayId = displayContent.getDisplayId();
9934            ScreenRotationAnimation screenRotationAnimation =
9935                    mAnimator.getScreenRotationAnimationLocked(displayId);
9936            if (screenRotationAnimation != null) {
9937                screenRotationAnimation.kill();
9938            }
9939
9940            // TODO(multidisplay): rotation on main screen only.
9941            screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent,
9942                    mFxSession, inTransaction, mPolicy.isDefaultOrientationForced());
9943            mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
9944        }
9945    }
9946
9947    private void stopFreezingDisplayLocked() {
9948        if (!mDisplayFrozen) {
9949            return;
9950        }
9951
9952        if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen
9953                || mClientFreezingScreen) {
9954            if (DEBUG_ORIENTATION) Slog.d(TAG,
9955                "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig
9956                + ", mAppsFreezingScreen=" + mAppsFreezingScreen
9957                + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen
9958                + ", mClientFreezingScreen=" + mClientFreezingScreen);
9959            return;
9960        }
9961
9962        mDisplayFrozen = false;
9963        mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime);
9964        StringBuilder sb = new StringBuilder(128);
9965        sb.append("Screen frozen for ");
9966        TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb);
9967        if (mLastFinishedFreezeSource != null) {
9968            sb.append(" due to ");
9969            sb.append(mLastFinishedFreezeSource);
9970        }
9971        Slog.i(TAG, sb.toString());
9972        mH.removeMessages(H.APP_FREEZE_TIMEOUT);
9973        mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
9974        if (PROFILE_ORIENTATION) {
9975            Debug.stopMethodTracing();
9976        }
9977
9978        boolean updateRotation = false;
9979
9980        final DisplayContent displayContent = getDefaultDisplayContentLocked();
9981        final int displayId = displayContent.getDisplayId();
9982        ScreenRotationAnimation screenRotationAnimation =
9983                mAnimator.getScreenRotationAnimationLocked(displayId);
9984        if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
9985                && screenRotationAnimation.hasScreenshot()) {
9986            if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation");
9987            // TODO(multidisplay): rotation on main screen only.
9988            DisplayInfo displayInfo = displayContent.getDisplayInfo();
9989            // Get rotation animation again, with new top window
9990            boolean isDimming = displayContent.isDimming();
9991            if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) {
9992                mExitAnimId = mEnterAnimId = 0;
9993            }
9994            if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
9995                    mTransitionAnimationScale, displayInfo.logicalWidth,
9996                        displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) {
9997                scheduleAnimationLocked();
9998            } else {
9999                screenRotationAnimation.kill();
10000                screenRotationAnimation = null;
10001                mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
10002                updateRotation = true;
10003            }
10004        } else {
10005            if (screenRotationAnimation != null) {
10006                screenRotationAnimation.kill();
10007                screenRotationAnimation = null;
10008                mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
10009            }
10010            updateRotation = true;
10011        }
10012
10013        mInputMonitor.thawInputDispatchingLw();
10014
10015        boolean configChanged;
10016
10017        // While the display is frozen we don't re-compute the orientation
10018        // to avoid inconsistent states.  However, something interesting
10019        // could have actually changed during that time so re-evaluate it
10020        // now to catch that.
10021        configChanged = updateOrientationFromAppTokensLocked(false);
10022
10023        // A little kludge: a lot could have happened while the
10024        // display was frozen, so now that we are coming back we
10025        // do a gc so that any remote references the system
10026        // processes holds on others can be released if they are
10027        // no longer needed.
10028        mH.removeMessages(H.FORCE_GC);
10029        mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000);
10030
10031        mScreenFrozenLock.release();
10032
10033        if (updateRotation) {
10034            if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
10035            configChanged |= updateRotationUncheckedLocked(false);
10036        }
10037
10038        if (configChanged) {
10039            mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
10040        }
10041    }
10042
10043    static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps,
10044            DisplayMetrics dm) {
10045        if (index < tokens.length) {
10046            String str = tokens[index];
10047            if (str != null && str.length() > 0) {
10048                try {
10049                    int val = Integer.parseInt(str);
10050                    return val;
10051                } catch (Exception e) {
10052                }
10053            }
10054        }
10055        if (defUnits == TypedValue.COMPLEX_UNIT_PX) {
10056            return defDps;
10057        }
10058        int val = (int)TypedValue.applyDimension(defUnits, defDps, dm);
10059        return val;
10060    }
10061
10062    void createWatermarkInTransaction() {
10063        if (mWatermark != null) {
10064            return;
10065        }
10066
10067        File file = new File("/system/etc/setup.conf");
10068        FileInputStream in = null;
10069        DataInputStream ind = null;
10070        try {
10071            in = new FileInputStream(file);
10072            ind = new DataInputStream(in);
10073            String line = ind.readLine();
10074            if (line != null) {
10075                String[] toks = line.split("%");
10076                if (toks != null && toks.length > 0) {
10077                    mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(),
10078                            mRealDisplayMetrics, mFxSession, toks);
10079                }
10080            }
10081        } catch (FileNotFoundException e) {
10082        } catch (IOException e) {
10083        } finally {
10084            if (ind != null) {
10085                try {
10086                    ind.close();
10087                } catch (IOException e) {
10088                }
10089            } else if (in != null) {
10090                try {
10091                    in.close();
10092                } catch (IOException e) {
10093                }
10094            }
10095        }
10096    }
10097
10098    @Override
10099    public void statusBarVisibilityChanged(int visibility) {
10100        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
10101                != PackageManager.PERMISSION_GRANTED) {
10102            throw new SecurityException("Caller does not hold permission "
10103                    + android.Manifest.permission.STATUS_BAR);
10104        }
10105
10106        synchronized (mWindowMap) {
10107            mLastStatusBarVisibility = visibility;
10108            visibility = mPolicy.adjustSystemUiVisibilityLw(visibility);
10109            updateStatusBarVisibilityLocked(visibility);
10110        }
10111    }
10112
10113    // TOOD(multidisplay): StatusBar on multiple screens?
10114    void updateStatusBarVisibilityLocked(int visibility) {
10115        mInputManager.setSystemUiVisibility(visibility);
10116        final WindowList windows = getDefaultWindowListLocked();
10117        final int N = windows.size();
10118        for (int i = 0; i < N; i++) {
10119            WindowState ws = windows.get(i);
10120            try {
10121                int curValue = ws.mSystemUiVisibility;
10122                int diff = curValue ^ visibility;
10123                // We are only interested in differences of one of the
10124                // clearable flags...
10125                diff &= View.SYSTEM_UI_CLEARABLE_FLAGS;
10126                // ...if it has actually been cleared.
10127                diff &= ~visibility;
10128                int newValue = (curValue&~diff) | (visibility&diff);
10129                if (newValue != curValue) {
10130                    ws.mSeq++;
10131                    ws.mSystemUiVisibility = newValue;
10132                }
10133                if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) {
10134                    ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq,
10135                            visibility, newValue, diff);
10136                }
10137            } catch (RemoteException e) {
10138                // so sorry
10139            }
10140        }
10141    }
10142
10143    @Override
10144    public void reevaluateStatusBarVisibility() {
10145        synchronized (mWindowMap) {
10146            int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility);
10147            updateStatusBarVisibilityLocked(visibility);
10148            performLayoutAndPlaceSurfacesLocked();
10149        }
10150    }
10151
10152    @Override
10153    public FakeWindow addFakeWindow(Looper looper,
10154            InputEventReceiver.Factory inputEventReceiverFactory,
10155            String name, int windowType, int layoutParamsFlags, int layoutParamsPrivateFlags,
10156            boolean canReceiveKeys, boolean hasFocus, boolean touchFullscreen) {
10157        synchronized (mWindowMap) {
10158            FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputEventReceiverFactory,
10159                    name, windowType,
10160                    layoutParamsFlags, layoutParamsPrivateFlags, canReceiveKeys,
10161                    hasFocus, touchFullscreen);
10162            int i=0;
10163            while (i<mFakeWindows.size()) {
10164                if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) {
10165                    break;
10166                }
10167            }
10168            mFakeWindows.add(i, fw);
10169            mInputMonitor.updateInputWindowsLw(true);
10170            return fw;
10171        }
10172    }
10173
10174    boolean removeFakeWindowLocked(FakeWindow window) {
10175        synchronized (mWindowMap) {
10176            if (mFakeWindows.remove(window)) {
10177                mInputMonitor.updateInputWindowsLw(true);
10178                return true;
10179            }
10180            return false;
10181        }
10182    }
10183
10184    // It is assumed that this method is called only by InputMethodManagerService.
10185    public void saveLastInputMethodWindowForTransition() {
10186        synchronized (mWindowMap) {
10187            // TODO(multidisplay): Pass in the displayID.
10188            DisplayContent displayContent = getDefaultDisplayContentLocked();
10189            if (mInputMethodWindow != null) {
10190                mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget);
10191            }
10192        }
10193    }
10194
10195    @Override
10196    public boolean hasNavigationBar() {
10197        return mPolicy.hasNavigationBar();
10198    }
10199
10200    @Override
10201    public void lockNow(Bundle options) {
10202        mPolicy.lockNow(options);
10203    }
10204
10205    @Override
10206    public boolean isSafeModeEnabled() {
10207        return mSafeMode;
10208    }
10209
10210    void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) {
10211        pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)");
10212        mPolicy.dump("    ", pw, args);
10213    }
10214
10215    void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) {
10216        pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)");
10217        mAnimator.dumpLocked(pw, "    ", dumpAll);
10218    }
10219
10220    void dumpTokensLocked(PrintWriter pw, boolean dumpAll) {
10221        pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)");
10222        if (mTokenMap.size() > 0) {
10223            pw.println("  All tokens:");
10224            Iterator<WindowToken> it = mTokenMap.values().iterator();
10225            while (it.hasNext()) {
10226                WindowToken token = it.next();
10227                pw.print("  "); pw.print(token);
10228                if (dumpAll) {
10229                    pw.println(':');
10230                    token.dump(pw, "    ");
10231                } else {
10232                    pw.println();
10233                }
10234            }
10235        }
10236        if (mWallpaperTokens.size() > 0) {
10237            pw.println();
10238            pw.println("  Wallpaper tokens:");
10239            for (int i=mWallpaperTokens.size()-1; i>=0; i--) {
10240                WindowToken token = mWallpaperTokens.get(i);
10241                pw.print("  Wallpaper #"); pw.print(i);
10242                        pw.print(' '); pw.print(token);
10243                if (dumpAll) {
10244                    pw.println(':');
10245                    token.dump(pw, "    ");
10246                } else {
10247                    pw.println();
10248                }
10249            }
10250        }
10251        if (mFinishedStarting.size() > 0) {
10252            pw.println();
10253            pw.println("  Finishing start of application tokens:");
10254            for (int i=mFinishedStarting.size()-1; i>=0; i--) {
10255                WindowToken token = mFinishedStarting.get(i);
10256                pw.print("  Finished Starting #"); pw.print(i);
10257                        pw.print(' '); pw.print(token);
10258                if (dumpAll) {
10259                    pw.println(':');
10260                    token.dump(pw, "    ");
10261                } else {
10262                    pw.println();
10263                }
10264            }
10265        }
10266        if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) {
10267            pw.println();
10268            if (mOpeningApps.size() > 0) {
10269                pw.print("  mOpeningApps="); pw.println(mOpeningApps);
10270            }
10271            if (mClosingApps.size() > 0) {
10272                pw.print("  mClosingApps="); pw.println(mClosingApps);
10273            }
10274        }
10275    }
10276
10277    void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) {
10278        pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)");
10279        if (mSessions.size() > 0) {
10280            Iterator<Session> it = mSessions.iterator();
10281            while (it.hasNext()) {
10282                Session s = it.next();
10283                pw.print("  Session "); pw.print(s); pw.println(':');
10284                s.dump(pw, "    ");
10285            }
10286        }
10287    }
10288
10289    void dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll) {
10290        pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)");
10291        if (mDisplayReady) {
10292            final int numDisplays = mDisplayContents.size();
10293            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10294                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
10295                displayContent.dump("  ", pw);
10296            }
10297        } else {
10298            pw.println("  NO DISPLAY");
10299        }
10300    }
10301
10302    void dumpWindowsLocked(PrintWriter pw, boolean dumpAll,
10303            ArrayList<WindowState> windows) {
10304        pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)");
10305        dumpWindowsNoHeaderLocked(pw, dumpAll, windows);
10306    }
10307
10308    void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll,
10309            ArrayList<WindowState> windows) {
10310        final int numDisplays = mDisplayContents.size();
10311        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10312            final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList();
10313            for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10314                final WindowState w = windowList.get(winNdx);
10315                if (windows == null || windows.contains(w)) {
10316                    pw.print("  Window #"); pw.print(winNdx); pw.print(' ');
10317                            pw.print(w); pw.println(":");
10318                    w.dump(pw, "    ", dumpAll || windows != null);
10319                }
10320            }
10321        }
10322        if (mInputMethodDialogs.size() > 0) {
10323            pw.println();
10324            pw.println("  Input method dialogs:");
10325            for (int i=mInputMethodDialogs.size()-1; i>=0; i--) {
10326                WindowState w = mInputMethodDialogs.get(i);
10327                if (windows == null || windows.contains(w)) {
10328                    pw.print("  IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w);
10329                }
10330            }
10331        }
10332        if (mPendingRemove.size() > 0) {
10333            pw.println();
10334            pw.println("  Remove pending for:");
10335            for (int i=mPendingRemove.size()-1; i>=0; i--) {
10336                WindowState w = mPendingRemove.get(i);
10337                if (windows == null || windows.contains(w)) {
10338                    pw.print("  Remove #"); pw.print(i); pw.print(' ');
10339                            pw.print(w);
10340                    if (dumpAll) {
10341                        pw.println(":");
10342                        w.dump(pw, "    ", true);
10343                    } else {
10344                        pw.println();
10345                    }
10346                }
10347            }
10348        }
10349        if (mForceRemoves != null && mForceRemoves.size() > 0) {
10350            pw.println();
10351            pw.println("  Windows force removing:");
10352            for (int i=mForceRemoves.size()-1; i>=0; i--) {
10353                WindowState w = mForceRemoves.get(i);
10354                pw.print("  Removing #"); pw.print(i); pw.print(' ');
10355                        pw.print(w);
10356                if (dumpAll) {
10357                    pw.println(":");
10358                    w.dump(pw, "    ", true);
10359                } else {
10360                    pw.println();
10361                }
10362            }
10363        }
10364        if (mDestroySurface.size() > 0) {
10365            pw.println();
10366            pw.println("  Windows waiting to destroy their surface:");
10367            for (int i=mDestroySurface.size()-1; i>=0; i--) {
10368                WindowState w = mDestroySurface.get(i);
10369                if (windows == null || windows.contains(w)) {
10370                    pw.print("  Destroy #"); pw.print(i); pw.print(' ');
10371                            pw.print(w);
10372                    if (dumpAll) {
10373                        pw.println(":");
10374                        w.dump(pw, "    ", true);
10375                    } else {
10376                        pw.println();
10377                    }
10378                }
10379            }
10380        }
10381        if (mLosingFocus.size() > 0) {
10382            pw.println();
10383            pw.println("  Windows losing focus:");
10384            for (int i=mLosingFocus.size()-1; i>=0; i--) {
10385                WindowState w = mLosingFocus.get(i);
10386                if (windows == null || windows.contains(w)) {
10387                    pw.print("  Losing #"); pw.print(i); pw.print(' ');
10388                            pw.print(w);
10389                    if (dumpAll) {
10390                        pw.println(":");
10391                        w.dump(pw, "    ", true);
10392                    } else {
10393                        pw.println();
10394                    }
10395                }
10396            }
10397        }
10398        if (mResizingWindows.size() > 0) {
10399            pw.println();
10400            pw.println("  Windows waiting to resize:");
10401            for (int i=mResizingWindows.size()-1; i>=0; i--) {
10402                WindowState w = mResizingWindows.get(i);
10403                if (windows == null || windows.contains(w)) {
10404                    pw.print("  Resizing #"); pw.print(i); pw.print(' ');
10405                            pw.print(w);
10406                    if (dumpAll) {
10407                        pw.println(":");
10408                        w.dump(pw, "    ", true);
10409                    } else {
10410                        pw.println();
10411                    }
10412                }
10413            }
10414        }
10415        if (mWaitingForDrawn.size() > 0) {
10416            pw.println();
10417            pw.println("  Clients waiting for these windows to be drawn:");
10418            for (int i=mWaitingForDrawn.size()-1; i>=0; i--) {
10419                Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(i);
10420                pw.print("  Waiting #"); pw.print(i); pw.print(' '); pw.print(pair.first);
10421                        pw.print(": "); pw.println(pair.second);
10422            }
10423        }
10424        pw.println();
10425        pw.print("  mCurConfiguration="); pw.println(this.mCurConfiguration);
10426        pw.print("  mCurrentFocus="); pw.println(mCurrentFocus);
10427        if (mLastFocus != mCurrentFocus) {
10428            pw.print("  mLastFocus="); pw.println(mLastFocus);
10429        }
10430        pw.print("  mFocusedApp="); pw.println(mFocusedApp);
10431        if (mInputMethodTarget != null) {
10432            pw.print("  mInputMethodTarget="); pw.println(mInputMethodTarget);
10433        }
10434        pw.print("  mInTouchMode="); pw.print(mInTouchMode);
10435                pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
10436        pw.print("  mLastDisplayFreezeDuration=");
10437                TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw);
10438                if ( mLastFinishedFreezeSource != null) {
10439                    pw.print(" due to ");
10440                    pw.print(mLastFinishedFreezeSource);
10441                }
10442                pw.println();
10443        if (dumpAll) {
10444            pw.print("  mSystemDecorLayer="); pw.print(mSystemDecorLayer);
10445                    pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString());
10446            if (mLastStatusBarVisibility != 0) {
10447                pw.print("  mLastStatusBarVisibility=0x");
10448                        pw.println(Integer.toHexString(mLastStatusBarVisibility));
10449            }
10450            if (mInputMethodWindow != null) {
10451                pw.print("  mInputMethodWindow="); pw.println(mInputMethodWindow);
10452            }
10453            pw.print("  mWallpaperTarget="); pw.println(mWallpaperTarget);
10454            if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) {
10455                pw.print("  mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget);
10456                pw.print("  mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget);
10457            }
10458            pw.print("  mLastWallpaperX="); pw.print(mLastWallpaperX);
10459                    pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
10460            if (mInputMethodAnimLayerAdjustment != 0 ||
10461                    mWallpaperAnimLayerAdjustment != 0) {
10462                pw.print("  mInputMethodAnimLayerAdjustment=");
10463                        pw.print(mInputMethodAnimLayerAdjustment);
10464                        pw.print("  mWallpaperAnimLayerAdjustment=");
10465                        pw.println(mWallpaperAnimLayerAdjustment);
10466            }
10467            pw.print("  mSystemBooted="); pw.print(mSystemBooted);
10468                    pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
10469            if (needsLayout()) {
10470                pw.print("  layoutNeeded on displays=");
10471                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10472                    final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
10473                    if (displayContent.layoutNeeded) {
10474                        pw.print(displayContent.getDisplayId());
10475                    }
10476                }
10477                pw.println();
10478            }
10479            pw.print("  mTransactionSequence="); pw.println(mTransactionSequence);
10480            pw.print("  mDisplayFrozen="); pw.print(mDisplayFrozen);
10481                    pw.print(" windows="); pw.print(mWindowsFreezingScreen);
10482                    pw.print(" client="); pw.print(mClientFreezingScreen);
10483                    pw.print(" apps="); pw.print(mAppsFreezingScreen);
10484                    pw.print(" waitingForConfig="); pw.println(mWaitingForConfig);
10485            pw.print("  mRotation="); pw.print(mRotation);
10486                    pw.print(" mAltOrientation="); pw.println(mAltOrientation);
10487            pw.print("  mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation);
10488                    pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation);
10489            pw.print("  mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount);
10490            pw.print("  mWindowAnimationScale="); pw.print(mWindowAnimationScale);
10491                    pw.print(" mTransitionWindowAnimationScale="); pw.print(mTransitionAnimationScale);
10492                    pw.print(" mAnimatorDurationScale="); pw.println(mAnimatorDurationScale);
10493            pw.print("  mTraversalScheduled="); pw.println(mTraversalScheduled);
10494            pw.print("  mStartingIconInTransition="); pw.print(mStartingIconInTransition);
10495                    pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
10496            pw.println("  mLayoutToAnim:");
10497            mAppTransition.dump(pw);
10498        }
10499    }
10500
10501    boolean dumpWindows(PrintWriter pw, String name, String[] args,
10502            int opti, boolean dumpAll) {
10503        WindowList windows = new WindowList();
10504        if ("visible".equals(name)) {
10505            synchronized(mWindowMap) {
10506                final int numDisplays = mDisplayContents.size();
10507                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10508                    final WindowList windowList =
10509                            mDisplayContents.valueAt(displayNdx).getWindowList();
10510                    for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10511                        final WindowState w = windowList.get(winNdx);
10512                        if (w.mWinAnimator.mSurfaceShown) {
10513                            windows.add(w);
10514                        }
10515                    }
10516                }
10517            }
10518        } else {
10519            int objectId = 0;
10520            // See if this is an object ID.
10521            try {
10522                objectId = Integer.parseInt(name, 16);
10523                name = null;
10524            } catch (RuntimeException e) {
10525            }
10526            synchronized(mWindowMap) {
10527                final int numDisplays = mDisplayContents.size();
10528                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10529                    final WindowList windowList =
10530                            mDisplayContents.valueAt(displayNdx).getWindowList();
10531                    for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10532                        final WindowState w = windowList.get(winNdx);
10533                        if (name != null) {
10534                            if (w.mAttrs.getTitle().toString().contains(name)) {
10535                                windows.add(w);
10536                            }
10537                        } else if (System.identityHashCode(w) == objectId) {
10538                            windows.add(w);
10539                        }
10540                    }
10541                }
10542            }
10543        }
10544
10545        if (windows.size() <= 0) {
10546            return false;
10547        }
10548
10549        synchronized(mWindowMap) {
10550            dumpWindowsLocked(pw, dumpAll, windows);
10551        }
10552        return true;
10553    }
10554
10555    void dumpLastANRLocked(PrintWriter pw) {
10556        pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)");
10557        if (mLastANRState == null) {
10558            pw.println("  <no ANR has occurred since boot>");
10559        } else {
10560            pw.println(mLastANRState);
10561        }
10562    }
10563
10564    /**
10565     * Saves information about the state of the window manager at
10566     * the time an ANR occurred before anything else in the system changes
10567     * in response.
10568     *
10569     * @param appWindowToken The application that ANR'd, may be null.
10570     * @param windowState The window that ANR'd, may be null.
10571     * @param reason The reason for the ANR, may be null.
10572     */
10573    public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState,
10574            String reason) {
10575        StringWriter sw = new StringWriter();
10576        PrintWriter pw = new FastPrintWriter(sw, false, 1024);
10577        pw.println("  ANR time: " + DateFormat.getInstance().format(new Date()));
10578        if (appWindowToken != null) {
10579            pw.println("  Application at fault: " + appWindowToken.stringName);
10580        }
10581        if (windowState != null) {
10582            pw.println("  Window at fault: " + windowState.mAttrs.getTitle());
10583        }
10584        if (reason != null) {
10585            pw.println("  Reason: " + reason);
10586        }
10587        pw.println();
10588        dumpWindowsNoHeaderLocked(pw, true, null);
10589        pw.close();
10590        mLastANRState = sw.toString();
10591    }
10592
10593    @Override
10594    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
10595        if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
10596                != PackageManager.PERMISSION_GRANTED) {
10597            pw.println("Permission Denial: can't dump WindowManager from from pid="
10598                    + Binder.getCallingPid()
10599                    + ", uid=" + Binder.getCallingUid());
10600            return;
10601        }
10602
10603        boolean dumpAll = false;
10604
10605        int opti = 0;
10606        while (opti < args.length) {
10607            String opt = args[opti];
10608            if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
10609                break;
10610            }
10611            opti++;
10612            if ("-a".equals(opt)) {
10613                dumpAll = true;
10614            } else if ("-h".equals(opt)) {
10615                pw.println("Window manager dump options:");
10616                pw.println("  [-a] [-h] [cmd] ...");
10617                pw.println("  cmd may be one of:");
10618                pw.println("    l[astanr]: last ANR information");
10619                pw.println("    p[policy]: policy state");
10620                pw.println("    a[animator]: animator state");
10621                pw.println("    s[essions]: active sessions");
10622                pw.println("    d[isplays]: active display contents");
10623                pw.println("    t[okens]: token list");
10624                pw.println("    w[indows]: window list");
10625                pw.println("  cmd may also be a NAME to dump windows.  NAME may");
10626                pw.println("    be a partial substring in a window name, a");
10627                pw.println("    Window hex object identifier, or");
10628                pw.println("    \"all\" for all windows, or");
10629                pw.println("    \"visible\" for the visible windows.");
10630                pw.println("  -a: include all available server state.");
10631                return;
10632            } else {
10633                pw.println("Unknown argument: " + opt + "; use -h for help");
10634            }
10635        }
10636
10637        // Is the caller requesting to dump a particular piece of data?
10638        if (opti < args.length) {
10639            String cmd = args[opti];
10640            opti++;
10641            if ("lastanr".equals(cmd) || "l".equals(cmd)) {
10642                synchronized(mWindowMap) {
10643                    dumpLastANRLocked(pw);
10644                }
10645                return;
10646            } else if ("policy".equals(cmd) || "p".equals(cmd)) {
10647                synchronized(mWindowMap) {
10648                    dumpPolicyLocked(pw, args, true);
10649                }
10650                return;
10651            } else if ("animator".equals(cmd) || "a".equals(cmd)) {
10652                synchronized(mWindowMap) {
10653                    dumpAnimatorLocked(pw, args, true);
10654                }
10655                return;
10656            } else if ("sessions".equals(cmd) || "s".equals(cmd)) {
10657                synchronized(mWindowMap) {
10658                    dumpSessionsLocked(pw, true);
10659                }
10660                return;
10661            } else if ("displays".equals(cmd) || "d".equals(cmd)) {
10662                synchronized(mWindowMap) {
10663                    dumpDisplayContentsLocked(pw, true);
10664                }
10665                return;
10666            } else if ("tokens".equals(cmd) || "t".equals(cmd)) {
10667                synchronized(mWindowMap) {
10668                    dumpTokensLocked(pw, true);
10669                }
10670                return;
10671            } else if ("windows".equals(cmd) || "w".equals(cmd)) {
10672                synchronized(mWindowMap) {
10673                    dumpWindowsLocked(pw, true, null);
10674                }
10675                return;
10676            } else if ("all".equals(cmd) || "a".equals(cmd)) {
10677                synchronized(mWindowMap) {
10678                    dumpWindowsLocked(pw, true, null);
10679                }
10680                return;
10681            } else {
10682                // Dumping a single name?
10683                if (!dumpWindows(pw, cmd, args, opti, dumpAll)) {
10684                    pw.println("Bad window command, or no windows match: " + cmd);
10685                    pw.println("Use -h for help.");
10686                }
10687                return;
10688            }
10689        }
10690
10691        synchronized(mWindowMap) {
10692            pw.println();
10693            if (dumpAll) {
10694                pw.println("-------------------------------------------------------------------------------");
10695            }
10696            dumpLastANRLocked(pw);
10697            pw.println();
10698            if (dumpAll) {
10699                pw.println("-------------------------------------------------------------------------------");
10700            }
10701            dumpPolicyLocked(pw, args, dumpAll);
10702            pw.println();
10703            if (dumpAll) {
10704                pw.println("-------------------------------------------------------------------------------");
10705            }
10706            dumpAnimatorLocked(pw, args, dumpAll);
10707            pw.println();
10708            if (dumpAll) {
10709                pw.println("-------------------------------------------------------------------------------");
10710            }
10711            dumpSessionsLocked(pw, dumpAll);
10712            pw.println();
10713            if (dumpAll) {
10714                pw.println("-------------------------------------------------------------------------------");
10715            }
10716            dumpDisplayContentsLocked(pw, dumpAll);
10717            pw.println();
10718            if (dumpAll) {
10719                pw.println("-------------------------------------------------------------------------------");
10720            }
10721            dumpTokensLocked(pw, dumpAll);
10722            pw.println();
10723            if (dumpAll) {
10724                pw.println("-------------------------------------------------------------------------------");
10725            }
10726            dumpWindowsLocked(pw, dumpAll, null);
10727        }
10728    }
10729
10730    // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection).
10731    @Override
10732    public void monitor() {
10733        synchronized (mWindowMap) { }
10734    }
10735
10736    public interface OnHardKeyboardStatusChangeListener {
10737        public void onHardKeyboardStatusChange(boolean available, boolean enabled);
10738    }
10739
10740    void debugLayoutRepeats(final String msg, int pendingLayoutChanges) {
10741        if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) {
10742            Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" +
10743                    Integer.toHexString(pendingLayoutChanges));
10744        }
10745    }
10746
10747    private DisplayContent newDisplayContentLocked(final Display display) {
10748        DisplayContent displayContent = new DisplayContent(display, this);
10749        final int displayId = display.getDisplayId();
10750        mDisplayContents.put(displayId, displayContent);
10751
10752        DisplayInfo displayInfo = displayContent.getDisplayInfo();
10753        final Rect rect = new Rect();
10754        mDisplaySettings.getOverscanLocked(displayInfo.name, rect);
10755        synchronized (displayContent.mDisplaySizeLock) {
10756            displayInfo.overscanLeft = rect.left;
10757            displayInfo.overscanTop = rect.top;
10758            displayInfo.overscanRight = rect.right;
10759            displayInfo.overscanBottom = rect.bottom;
10760            mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
10761                    displayId, displayInfo);
10762        }
10763        configureDisplayPolicyLocked(displayContent);
10764
10765        // TODO: Create an input channel for each display with touch capability.
10766        if (displayId == Display.DEFAULT_DISPLAY) {
10767            displayContent.mTapDetector = new StackTapPointerEventListener(this, displayContent);
10768            registerPointerEventListener(displayContent.mTapDetector);
10769        }
10770
10771        return displayContent;
10772    }
10773
10774    public void createDisplayContentLocked(final Display display) {
10775        if (display == null) {
10776            throw new IllegalArgumentException("getDisplayContent: display must not be null");
10777        }
10778        getDisplayContentLocked(display.getDisplayId());
10779    }
10780
10781    /**
10782     * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if
10783     * there is a Display for the displayId.
10784     * @param displayId The display the caller is interested in.
10785     * @return The DisplayContent associated with displayId or null if there is no Display for it.
10786     */
10787    public DisplayContent getDisplayContentLocked(final int displayId) {
10788        DisplayContent displayContent = mDisplayContents.get(displayId);
10789        if (displayContent == null) {
10790            final Display display = mDisplayManager.getDisplay(displayId);
10791            if (display != null) {
10792                displayContent = newDisplayContentLocked(display);
10793            }
10794        }
10795        return displayContent;
10796    }
10797
10798    // There is an inherent assumption that this will never return null.
10799    public DisplayContent getDefaultDisplayContentLocked() {
10800        return getDisplayContentLocked(Display.DEFAULT_DISPLAY);
10801    }
10802
10803    public WindowList getDefaultWindowListLocked() {
10804        return getDefaultDisplayContentLocked().getWindowList();
10805    }
10806
10807    public DisplayInfo getDefaultDisplayInfoLocked() {
10808        return getDefaultDisplayContentLocked().getDisplayInfo();
10809    }
10810
10811    /**
10812     * Return the list of WindowStates associated on the passed display.
10813     * @param display The screen to return windows from.
10814     * @return The list of WindowStates on the screen, or null if the there is no screen.
10815     */
10816    public WindowList getWindowListLocked(final Display display) {
10817        return getWindowListLocked(display.getDisplayId());
10818    }
10819
10820    /**
10821     * Return the list of WindowStates associated on the passed display.
10822     * @param displayId The screen to return windows from.
10823     * @return The list of WindowStates on the screen, or null if the there is no screen.
10824     */
10825    public WindowList getWindowListLocked(final int displayId) {
10826        final DisplayContent displayContent = getDisplayContentLocked(displayId);
10827        return displayContent != null ? displayContent.getWindowList() : null;
10828    }
10829
10830    public void onDisplayAdded(int displayId) {
10831        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0));
10832    }
10833
10834    public void handleDisplayAdded(int displayId) {
10835        synchronized (mWindowMap) {
10836            final Display display = mDisplayManager.getDisplay(displayId);
10837            if (display != null) {
10838                createDisplayContentLocked(display);
10839                displayReady(displayId);
10840            }
10841        }
10842    }
10843
10844    public void onDisplayRemoved(int displayId) {
10845        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0));
10846    }
10847
10848    private void handleDisplayRemovedLocked(int displayId) {
10849        final DisplayContent displayContent = getDisplayContentLocked(displayId);
10850        if (displayContent != null) {
10851            mDisplayContents.delete(displayId);
10852            displayContent.close();
10853            if (displayId == Display.DEFAULT_DISPLAY) {
10854                unregisterPointerEventListener(displayContent.mTapDetector);
10855            }
10856        }
10857        mAnimator.removeDisplayLocked(displayId);
10858    }
10859
10860    public void onDisplayChanged(int displayId) {
10861        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0));
10862    }
10863
10864    private void handleDisplayChangedLocked(int displayId) {
10865        final DisplayContent displayContent = getDisplayContentLocked(displayId);
10866        if (displayContent != null) {
10867            displayContent.updateDisplayInfo();
10868        }
10869    }
10870
10871    @Override
10872    public Object getWindowManagerLock() {
10873        return mWindowMap;
10874    }
10875
10876    private final class LocalService extends WindowManagerInternal {
10877        @Override
10878        public void requestTraversalFromDisplayManager() {
10879            requestTraversal();
10880        }
10881    }
10882}
10883