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