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