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