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