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