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