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