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