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