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