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