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