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