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