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