WindowManagerService.java revision 4e8a19c73a0b4ca91ea963230948841054495631
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 " + 0);
1859                }
1860
1861                windows.add(0, 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        stack.addTask(task, true);
3390        stack.getDisplayContent().moveStack(stack, true);
3391        mTaskIdToTask.put(taskId, task);
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        // Never put an app window underneath wallpaper.
4675        for (int pos = NW - 1; pos >= 0; pos--) {
4676            if (windows.get(pos).mIsWallpaper) {
4677                if (DEBUG_REORDER) Slog.v(TAG, "Found wallpaper @" + pos);
4678                return pos + 1;
4679            }
4680        }
4681        return 0;
4682    }
4683
4684    private final int reAddWindowLocked(int index, WindowState win) {
4685        final WindowList windows = win.getWindowList();
4686        final int NCW = win.mChildWindows.size();
4687        boolean added = false;
4688        for (int j=0; j<NCW; j++) {
4689            WindowState cwin = win.mChildWindows.get(j);
4690            if (!added && cwin.mSubLayer >= 0) {
4691                if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding child window at "
4692                        + index + ": " + cwin);
4693                win.mRebuilding = false;
4694                windows.add(index, win);
4695                index++;
4696                added = true;
4697            }
4698            if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
4699                    + index + ": " + cwin);
4700            cwin.mRebuilding = false;
4701            windows.add(index, cwin);
4702            index++;
4703        }
4704        if (!added) {
4705            if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
4706                    + index + ": " + win);
4707            win.mRebuilding = false;
4708            windows.add(index, win);
4709            index++;
4710        }
4711        mWindowsChanged = true;
4712        return index;
4713    }
4714
4715    private final int reAddAppWindowsLocked(final DisplayContent displayContent, int index,
4716                                            WindowToken token) {
4717        final int NW = token.windows.size();
4718        for (int i=0; i<NW; i++) {
4719            final WindowState win = token.windows.get(i);
4720            if (win.mDisplayContent == displayContent) {
4721                index = reAddWindowLocked(index, win);
4722            }
4723        }
4724        return index;
4725    }
4726
4727    private void moveHomeTasksLocked(boolean toTop) {
4728        final DisplayContent displayContent = getDefaultDisplayContentLocked();
4729        if (toTop ^ displayContent.homeOnTop()) {
4730            final ArrayList<Task> tasks = displayContent.getHomeStack().getTasks();
4731            final int numTasks = tasks.size();
4732            for (int i = 0; i < numTasks; ++i) {
4733                if (toTop) {
4734                    // Keep pulling the bottom task off and moving it to the top.
4735                    moveTaskToTop(tasks.get(0).taskId);
4736                } else {
4737                    // Keep pulling the top task off and moving it to the bottom.
4738                    moveTaskToBottom(tasks.get(numTasks - 1).taskId);
4739                }
4740            }
4741        }
4742    }
4743
4744    void moveStackWindowsLocked(TaskStack stack) {
4745        DisplayContent displayContent = stack.getDisplayContent();
4746
4747        // First remove all of the windows from the list.
4748        final ArrayList<Task> tasks = stack.getTasks();
4749        final int numTasks = tasks.size();
4750        for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
4751            AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
4752            final int numTokens = tokens.size();
4753            for (int tokenNdx = numTokens - 1; tokenNdx >= 0; --tokenNdx) {
4754                tmpRemoveAppWindowsLocked(tokens.get(tokenNdx));
4755            }
4756        }
4757
4758        // And now add them back at the correct place.
4759        // Where to start adding?
4760        for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
4761            AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
4762            int pos = findAppWindowInsertionPointLocked(tokens.get(0));
4763            final int numTokens = tokens.size();
4764            for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
4765                final AppWindowToken wtoken = tokens.get(tokenNdx);
4766                if (wtoken != null) {
4767                    final int newPos = reAddAppWindowsLocked(displayContent, pos, wtoken);
4768                    if (newPos != pos) {
4769                        displayContent.layoutNeeded = true;
4770                    }
4771                    pos = newPos;
4772                }
4773            }
4774        }
4775
4776        if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
4777                false /*updateInputWindows*/)) {
4778            assignLayersLocked(displayContent.getWindowList());
4779        }
4780
4781        mInputMonitor.setUpdateInputWindowsNeededLw();
4782        performLayoutAndPlaceSurfacesLocked();
4783        mInputMonitor.updateInputWindowsLw(false /*force*/);
4784
4785        //dump();
4786    }
4787
4788    public void moveTaskToTop(int taskId) {
4789        final long origId = Binder.clearCallingIdentity();
4790        try {
4791            synchronized(mWindowMap) {
4792                Task task = mTaskIdToTask.get(taskId);
4793                if (task == null) {
4794                    // Normal behavior, addAppToken will be called next and task will be created.
4795                    return;
4796                }
4797                final TaskStack stack = task.mStack;
4798                final DisplayContent displayContent = task.getDisplayContent();
4799                final boolean isHomeStackTask = stack.isHomeStack();
4800                final boolean homeIsOnTop = displayContent.homeOnTop();
4801                if (!isHomeStackTask && homeIsOnTop) {
4802                    // First move move the home tasks all to the bottom to rearrange the windows.
4803                    moveHomeTasksLocked(false);
4804                    // Now move the stack itself.
4805                    displayContent.moveHomeStackBox(false);
4806                } else if (isHomeStackTask && !homeIsOnTop) {
4807                    // Move the stack to the top.
4808                    displayContent.moveHomeStackBox(true);
4809                }
4810                stack.moveTaskToTop(task);
4811                displayContent.moveStack(stack, true);
4812            }
4813        } finally {
4814            Binder.restoreCallingIdentity(origId);
4815        }
4816    }
4817
4818    public void moveTaskToBottom(int taskId) {
4819        final long origId = Binder.clearCallingIdentity();
4820        try {
4821            synchronized(mWindowMap) {
4822                Task task = mTaskIdToTask.get(taskId);
4823                if (task == null) {
4824                    Slog.e(TAG, "moveTaskToBottom: taskId=" + taskId
4825                            + " not found in mTaskIdToTask");
4826                    return;
4827                }
4828                final TaskStack stack = task.mStack;
4829                stack.moveTaskToBottom(task);
4830                moveStackWindowsLocked(stack);
4831            }
4832        } finally {
4833            Binder.restoreCallingIdentity(origId);
4834        }
4835    }
4836
4837    /**
4838     * Create a new TaskStack and place it next to an existing stack.
4839     * @param stackId The unique identifier of the new stack.
4840     * @param relativeStackBoxId The existing stack that this stack goes before or after.
4841     * @param position One of:
4842     *      {@link StackBox#TASK_STACK_GOES_BEFORE}
4843     *      {@link StackBox#TASK_STACK_GOES_AFTER}
4844     *      {@link StackBox#TASK_STACK_GOES_ABOVE}
4845     *      {@link StackBox#TASK_STACK_GOES_BELOW}
4846     *      {@link StackBox#TASK_STACK_GOES_UNDER}
4847     *      {@link StackBox#TASK_STACK_GOES_OVER}
4848     * @param weight Relative weight for determining how big to make the new TaskStack.
4849     */
4850    public void createStack(int stackId, int relativeStackBoxId, int position, float weight) {
4851        synchronized (mWindowMap) {
4852            if (position <= StackBox.TASK_STACK_GOES_BELOW &&
4853                    (weight < STACK_WEIGHT_MIN || weight > STACK_WEIGHT_MAX)) {
4854                throw new IllegalArgumentException(
4855                        "createStack: weight must be between " + STACK_WEIGHT_MIN + " and " +
4856                        STACK_WEIGHT_MAX + ", weight=" + weight);
4857            }
4858            final int numDisplays = mDisplayContents.size();
4859            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
4860                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
4861                TaskStack stack = displayContent.createStack(stackId, relativeStackBoxId, position,
4862                        weight);
4863                if (stack != null) {
4864                    mStackIdToStack.put(stackId, stack);
4865                    displayContent.moveStack(stack, true);
4866                    performLayoutAndPlaceSurfacesLocked();
4867                    return;
4868                }
4869            }
4870            Slog.e(TAG, "createStack: Unable to find relativeStackBoxId=" + relativeStackBoxId);
4871        }
4872    }
4873
4874    public int removeStack(int stackId) {
4875        synchronized (mWindowMap) {
4876            final TaskStack stack = mStackIdToStack.get(stackId);
4877            if (stack != null) {
4878                mStackIdToStack.delete(stackId);
4879                int nextStackId = stack.remove();
4880                stack.getDisplayContent().layoutNeeded = true;
4881                requestTraversalLocked();
4882                return nextStackId;
4883            }
4884            if (DEBUG_STACK) Slog.i(TAG, "removeStack: could not find stackId=" + stackId);
4885        }
4886        return HOME_STACK_ID;
4887    }
4888
4889    public void removeTask(int taskId) {
4890        synchronized (mWindowMap) {
4891            Task task = mTaskIdToTask.get(taskId);
4892            if (task == null) {
4893                if (DEBUG_STACK) Slog.i(TAG, "removeTask: could not find taskId=" + taskId);
4894                return;
4895            }
4896            final TaskStack stack = task.mStack;
4897            stack.removeTask(task);
4898            stack.getDisplayContent().layoutNeeded = true;
4899        }
4900    }
4901
4902    public void addTask(int taskId, int stackId, boolean toTop) {
4903        synchronized (mWindowMap) {
4904            Task task = mTaskIdToTask.get(taskId);
4905            if (task == null) {
4906                return;
4907            }
4908            TaskStack stack = mStackIdToStack.get(stackId);
4909            stack.addTask(task, toTop);
4910            final DisplayContent displayContent = stack.getDisplayContent();
4911            displayContent.layoutNeeded = true;
4912            performLayoutAndPlaceSurfacesLocked();
4913        }
4914    }
4915
4916    public void resizeStackBox(int stackBoxId, float weight) {
4917        if (weight < STACK_WEIGHT_MIN || weight > STACK_WEIGHT_MAX) {
4918            throw new IllegalArgumentException(
4919                    "resizeStack: weight must be between " + STACK_WEIGHT_MIN + " and " +
4920                    STACK_WEIGHT_MAX + ", weight=" + weight);
4921        }
4922        synchronized (mWindowMap) {
4923            final int numDisplays = mDisplayContents.size();
4924            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
4925                if (mDisplayContents.valueAt(displayNdx).resizeStack(stackBoxId, weight)) {
4926                    performLayoutAndPlaceSurfacesLocked();
4927                    return;
4928                }
4929            }
4930        }
4931        throw new IllegalArgumentException("resizeStack: stackBoxId " + stackBoxId
4932                + " not found.");
4933    }
4934
4935    public ArrayList<StackBoxInfo> getStackBoxInfos() {
4936        synchronized(mWindowMap) {
4937            return getDefaultDisplayContentLocked().getStackBoxInfos();
4938        }
4939    }
4940
4941    public Rect getStackBounds(int stackId) {
4942        final int numDisplays = mDisplayContents.size();
4943        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
4944            Rect bounds = mDisplayContents.valueAt(displayNdx).getStackBounds(stackId);
4945            if (bounds != null) {
4946                return bounds;
4947            }
4948        }
4949        return null;
4950    }
4951
4952    // -------------------------------------------------------------
4953    // Misc IWindowSession methods
4954    // -------------------------------------------------------------
4955
4956    @Override
4957    public void startFreezingScreen(int exitAnim, int enterAnim) {
4958        if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
4959                "startFreezingScreen()")) {
4960            throw new SecurityException("Requires FREEZE_SCREEN permission");
4961        }
4962
4963        synchronized(mWindowMap) {
4964            if (!mClientFreezingScreen) {
4965                mClientFreezingScreen = true;
4966                final long origId = Binder.clearCallingIdentity();
4967                try {
4968                    startFreezingDisplayLocked(false, exitAnim, enterAnim);
4969                    mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
4970                    mH.sendEmptyMessageDelayed(H.CLIENT_FREEZE_TIMEOUT, 5000);
4971                } finally {
4972                    Binder.restoreCallingIdentity(origId);
4973                }
4974            }
4975        }
4976    }
4977
4978    @Override
4979    public void stopFreezingScreen() {
4980        if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
4981                "stopFreezingScreen()")) {
4982            throw new SecurityException("Requires FREEZE_SCREEN permission");
4983        }
4984
4985        synchronized(mWindowMap) {
4986            if (mClientFreezingScreen) {
4987                mClientFreezingScreen = false;
4988                mLastFinishedFreezeSource = "client";
4989                final long origId = Binder.clearCallingIdentity();
4990                try {
4991                    stopFreezingDisplayLocked();
4992                } finally {
4993                    Binder.restoreCallingIdentity(origId);
4994                }
4995            }
4996        }
4997    }
4998
4999    @Override
5000    public void disableKeyguard(IBinder token, String tag) {
5001        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5002            != PackageManager.PERMISSION_GRANTED) {
5003            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5004        }
5005
5006        mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
5007                KeyguardDisableHandler.KEYGUARD_DISABLE, new Pair<IBinder, String>(token, tag)));
5008    }
5009
5010    @Override
5011    public void reenableKeyguard(IBinder token) {
5012        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5013            != PackageManager.PERMISSION_GRANTED) {
5014            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5015        }
5016
5017        mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
5018                KeyguardDisableHandler.KEYGUARD_REENABLE, token));
5019    }
5020
5021    /**
5022     * @see android.app.KeyguardManager#exitKeyguardSecurely
5023     */
5024    @Override
5025    public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) {
5026        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5027            != PackageManager.PERMISSION_GRANTED) {
5028            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5029        }
5030        mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() {
5031            @Override
5032            public void onKeyguardExitResult(boolean success) {
5033                try {
5034                    callback.onKeyguardExitResult(success);
5035                } catch (RemoteException e) {
5036                    // Client has died, we don't care.
5037                }
5038            }
5039        });
5040    }
5041
5042    @Override
5043    public boolean inKeyguardRestrictedInputMode() {
5044        return mPolicy.inKeyguardRestrictedKeyInputMode();
5045    }
5046
5047    @Override
5048    public boolean isKeyguardLocked() {
5049        return mPolicy.isKeyguardLocked();
5050    }
5051
5052    @Override
5053    public boolean isKeyguardSecure() {
5054        return mPolicy.isKeyguardSecure();
5055    }
5056
5057    @Override
5058    public void dismissKeyguard() {
5059        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5060                != PackageManager.PERMISSION_GRANTED) {
5061            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5062        }
5063        synchronized(mWindowMap) {
5064            mPolicy.dismissKeyguardLw();
5065        }
5066    }
5067
5068    @Override
5069    public void closeSystemDialogs(String reason) {
5070        synchronized(mWindowMap) {
5071            final int numDisplays = mDisplayContents.size();
5072            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5073                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
5074                final int numWindows = windows.size();
5075                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
5076                    final WindowState w = windows.get(winNdx);
5077                    if (w.mHasSurface) {
5078                        try {
5079                            w.mClient.closeSystemDialogs(reason);
5080                        } catch (RemoteException e) {
5081                        }
5082                    }
5083                }
5084            }
5085        }
5086    }
5087
5088    static float fixScale(float scale) {
5089        if (scale < 0) scale = 0;
5090        else if (scale > 20) scale = 20;
5091        return Math.abs(scale);
5092    }
5093
5094    @Override
5095    public void setAnimationScale(int which, float scale) {
5096        if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
5097                "setAnimationScale()")) {
5098            throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
5099        }
5100
5101        scale = fixScale(scale);
5102        switch (which) {
5103            case 0: mWindowAnimationScale = scale; break;
5104            case 1: mTransitionAnimationScale = scale; break;
5105            case 2: mAnimatorDurationScale = scale; break;
5106        }
5107
5108        // Persist setting
5109        mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
5110    }
5111
5112    @Override
5113    public void setAnimationScales(float[] scales) {
5114        if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
5115                "setAnimationScale()")) {
5116            throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
5117        }
5118
5119        if (scales != null) {
5120            if (scales.length >= 1) {
5121                mWindowAnimationScale = fixScale(scales[0]);
5122            }
5123            if (scales.length >= 2) {
5124                mTransitionAnimationScale = fixScale(scales[1]);
5125            }
5126            if (scales.length >= 3) {
5127                setAnimatorDurationScale(fixScale(scales[2]));
5128            }
5129        }
5130
5131        // Persist setting
5132        mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
5133    }
5134
5135    private void setAnimatorDurationScale(float scale) {
5136        mAnimatorDurationScale = scale;
5137        ValueAnimator.setDurationScale(scale);
5138    }
5139
5140    @Override
5141    public float getAnimationScale(int which) {
5142        switch (which) {
5143            case 0: return mWindowAnimationScale;
5144            case 1: return mTransitionAnimationScale;
5145            case 2: return mAnimatorDurationScale;
5146        }
5147        return 0;
5148    }
5149
5150    @Override
5151    public float[] getAnimationScales() {
5152        return new float[] { mWindowAnimationScale, mTransitionAnimationScale,
5153                mAnimatorDurationScale };
5154    }
5155
5156    @Override
5157    public void registerPointerEventListener(PointerEventListener listener) {
5158        mPointerEventDispatcher.registerInputEventListener(listener);
5159    }
5160
5161    @Override
5162    public void unregisterPointerEventListener(PointerEventListener listener) {
5163        mPointerEventDispatcher.unregisterInputEventListener(listener);
5164    }
5165
5166    // Called by window manager policy. Not exposed externally.
5167    @Override
5168    public int getLidState() {
5169        int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY,
5170                InputManagerService.SW_LID);
5171        if (sw > 0) {
5172            // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL.
5173            return LID_CLOSED;
5174        } else if (sw == 0) {
5175            // Switch state: AKEY_STATE_UP.
5176            return LID_OPEN;
5177        } else {
5178            // Switch state: AKEY_STATE_UNKNOWN.
5179            return LID_ABSENT;
5180        }
5181    }
5182
5183    // Called by window manager policy.  Not exposed externally.
5184    @Override
5185    public void switchKeyboardLayout(int deviceId, int direction) {
5186        mInputManager.switchKeyboardLayout(deviceId, direction);
5187    }
5188
5189    // Called by window manager policy.  Not exposed externally.
5190    @Override
5191    public void shutdown(boolean confirm) {
5192        ShutdownThread.shutdown(mContext, confirm);
5193    }
5194
5195    // Called by window manager policy.  Not exposed externally.
5196    @Override
5197    public void rebootSafeMode(boolean confirm) {
5198        ShutdownThread.rebootSafeMode(mContext, confirm);
5199    }
5200
5201    @Override
5202    public void setInputFilter(IInputFilter filter) {
5203        if (!checkCallingPermission(android.Manifest.permission.FILTER_EVENTS, "setInputFilter()")) {
5204            throw new SecurityException("Requires FILTER_EVENTS permission");
5205        }
5206        mInputManager.setInputFilter(filter);
5207    }
5208
5209    public void setCurrentUser(final int newUserId) {
5210        synchronized (mWindowMap) {
5211            int oldUserId = mCurrentUserId;
5212            mCurrentUserId = newUserId;
5213            mAppTransition.setCurrentUser(newUserId);
5214            mPolicy.setCurrentUserLw(newUserId);
5215
5216            // Hide windows that should not be seen by the new user.
5217            final int numDisplays = mDisplayContents.size();
5218            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5219                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
5220                displayContent.switchUserStacks(oldUserId, newUserId);
5221                rebuildAppWindowListLocked(displayContent);
5222            }
5223            performLayoutAndPlaceSurfacesLocked();
5224        }
5225    }
5226
5227    public void enableScreenAfterBoot() {
5228        synchronized(mWindowMap) {
5229            if (DEBUG_BOOT) {
5230                RuntimeException here = new RuntimeException("here");
5231                here.fillInStackTrace();
5232                Slog.i(TAG, "enableScreenAfterBoot: mDisplayEnabled=" + mDisplayEnabled
5233                        + " mForceDisplayEnabled=" + mForceDisplayEnabled
5234                        + " mShowingBootMessages=" + mShowingBootMessages
5235                        + " mSystemBooted=" + mSystemBooted, here);
5236            }
5237            if (mSystemBooted) {
5238                return;
5239            }
5240            mSystemBooted = true;
5241            hideBootMessagesLocked();
5242            // If the screen still doesn't come up after 30 seconds, give
5243            // up and turn it on.
5244            mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30*1000);
5245        }
5246
5247        mPolicy.systemBooted();
5248
5249        performEnableScreen();
5250    }
5251
5252    void enableScreenIfNeededLocked() {
5253        if (DEBUG_BOOT) {
5254            RuntimeException here = new RuntimeException("here");
5255            here.fillInStackTrace();
5256            Slog.i(TAG, "enableScreenIfNeededLocked: mDisplayEnabled=" + mDisplayEnabled
5257                    + " mForceDisplayEnabled=" + mForceDisplayEnabled
5258                    + " mShowingBootMessages=" + mShowingBootMessages
5259                    + " mSystemBooted=" + mSystemBooted, here);
5260        }
5261        if (mDisplayEnabled) {
5262            return;
5263        }
5264        if (!mSystemBooted && !mShowingBootMessages) {
5265            return;
5266        }
5267        mH.sendEmptyMessage(H.ENABLE_SCREEN);
5268    }
5269
5270    public void performBootTimeout() {
5271        synchronized(mWindowMap) {
5272            if (mDisplayEnabled || mHeadless) {
5273                return;
5274            }
5275            Slog.w(TAG, "***** BOOT TIMEOUT: forcing display enabled");
5276            mForceDisplayEnabled = true;
5277        }
5278        performEnableScreen();
5279    }
5280
5281    public void performEnableScreen() {
5282        synchronized(mWindowMap) {
5283            if (DEBUG_BOOT) {
5284                RuntimeException here = new RuntimeException("here");
5285                here.fillInStackTrace();
5286                Slog.i(TAG, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled
5287                        + " mForceDisplayEnabled=" + mForceDisplayEnabled
5288                        + " mShowingBootMessages=" + mShowingBootMessages
5289                        + " mSystemBooted=" + mSystemBooted
5290                        + " mOnlyCore=" + mOnlyCore, here);
5291            }
5292            if (mDisplayEnabled) {
5293                return;
5294            }
5295            if (!mSystemBooted && !mShowingBootMessages) {
5296                return;
5297            }
5298
5299            if (!mForceDisplayEnabled) {
5300                // Don't enable the screen until all existing windows
5301                // have been drawn.
5302                boolean haveBootMsg = false;
5303                boolean haveApp = false;
5304                // if the wallpaper service is disabled on the device, we're never going to have
5305                // wallpaper, don't bother waiting for it
5306                boolean haveWallpaper = false;
5307                boolean wallpaperEnabled = mContext.getResources().getBoolean(
5308                        com.android.internal.R.bool.config_enableWallpaperService)
5309                        && !mOnlyCore;
5310                boolean haveKeyguard = true;
5311                // TODO(multidisplay): Expand to all displays?
5312                final WindowList windows = getDefaultWindowListLocked();
5313                final int N = windows.size();
5314                for (int i=0; i<N; i++) {
5315                    WindowState w = windows.get(i);
5316                    if (w.mAttrs.type == TYPE_KEYGUARD) {
5317                        // Only if there is a keyguard attached to the window manager
5318                        // will we consider ourselves as having a keyguard.  If it
5319                        // isn't attached, we don't know if it wants to be shown or
5320                        // hidden.  If it is attached, we will say we have a keyguard
5321                        // if the window doesn't want to be visible, because in that
5322                        // case it explicitly doesn't want to be shown so we should
5323                        // not delay turning the screen on for it.
5324                        boolean vis = w.mViewVisibility == View.VISIBLE
5325                                && w.mPolicyVisibility;
5326                        haveKeyguard = !vis;
5327                    }
5328                    if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
5329                        return;
5330                    }
5331                    if (w.isDrawnLw()) {
5332                        if (w.mAttrs.type == TYPE_BOOT_PROGRESS) {
5333                            haveBootMsg = true;
5334                        } else if (w.mAttrs.type == TYPE_APPLICATION) {
5335                            haveApp = true;
5336                        } else if (w.mAttrs.type == TYPE_WALLPAPER) {
5337                            haveWallpaper = true;
5338                        } else if (w.mAttrs.type == TYPE_KEYGUARD) {
5339                            haveKeyguard = true;
5340                        }
5341                    }
5342                }
5343
5344                if (DEBUG_SCREEN_ON || DEBUG_BOOT) {
5345                    Slog.i(TAG, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages
5346                            + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp
5347                            + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled
5348                            + " haveKeyguard=" + haveKeyguard);
5349                }
5350
5351                // If we are turning on the screen to show the boot message,
5352                // don't do it until the boot message is actually displayed.
5353                if (!mSystemBooted && !haveBootMsg) {
5354                    return;
5355                }
5356
5357                // If we are turning on the screen after the boot is completed
5358                // normally, don't do so until we have the application and
5359                // wallpaper.
5360                if (mSystemBooted && ((!haveApp && !haveKeyguard) ||
5361                        (wallpaperEnabled && !haveWallpaper))) {
5362                    return;
5363                }
5364            }
5365
5366            mDisplayEnabled = true;
5367            if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG, "******************** ENABLING SCREEN!");
5368            if (false) {
5369                StringWriter sw = new StringWriter();
5370                PrintWriter pw = new FastPrintWriter(sw, false, 1024);
5371                this.dump(null, pw, null);
5372                pw.flush();
5373                Slog.i(TAG, sw.toString());
5374            }
5375            try {
5376                IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
5377                if (surfaceFlinger != null) {
5378                    //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
5379                    Parcel data = Parcel.obtain();
5380                    data.writeInterfaceToken("android.ui.ISurfaceComposer");
5381                    surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
5382                                            data, null, 0);
5383                    data.recycle();
5384                }
5385            } catch (RemoteException ex) {
5386                Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!");
5387            }
5388
5389            // Enable input dispatch.
5390            mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled);
5391        }
5392
5393        mPolicy.enableScreenAfterBoot();
5394
5395        // Make sure the last requested orientation has been applied.
5396        updateRotationUnchecked(false, false);
5397    }
5398
5399    public void showBootMessage(final CharSequence msg, final boolean always) {
5400        boolean first = false;
5401        synchronized(mWindowMap) {
5402            if (DEBUG_BOOT) {
5403                RuntimeException here = new RuntimeException("here");
5404                here.fillInStackTrace();
5405                Slog.i(TAG, "showBootMessage: msg=" + msg + " always=" + always
5406                        + " mAllowBootMessages=" + mAllowBootMessages
5407                        + " mShowingBootMessages=" + mShowingBootMessages
5408                        + " mSystemBooted=" + mSystemBooted, here);
5409            }
5410            if (!mAllowBootMessages) {
5411                return;
5412            }
5413            if (!mShowingBootMessages) {
5414                if (!always) {
5415                    return;
5416                }
5417                first = true;
5418            }
5419            if (mSystemBooted) {
5420                return;
5421            }
5422            mShowingBootMessages = true;
5423            mPolicy.showBootMessage(msg, always);
5424        }
5425        if (first) {
5426            performEnableScreen();
5427        }
5428    }
5429
5430    public void hideBootMessagesLocked() {
5431        if (DEBUG_BOOT) {
5432            RuntimeException here = new RuntimeException("here");
5433            here.fillInStackTrace();
5434            Slog.i(TAG, "hideBootMessagesLocked: mDisplayEnabled=" + mDisplayEnabled
5435                    + " mForceDisplayEnabled=" + mForceDisplayEnabled
5436                    + " mShowingBootMessages=" + mShowingBootMessages
5437                    + " mSystemBooted=" + mSystemBooted, here);
5438        }
5439        if (mShowingBootMessages) {
5440            mShowingBootMessages = false;
5441            mPolicy.hideBootMessages();
5442        }
5443    }
5444
5445    @Override
5446    public void setInTouchMode(boolean mode) {
5447        synchronized(mWindowMap) {
5448            mInTouchMode = mode;
5449        }
5450    }
5451
5452    // TODO: more accounting of which pid(s) turned it on, keep count,
5453    // only allow disables from pids which have count on, etc.
5454    @Override
5455    public void showStrictModeViolation(boolean on) {
5456        if (mHeadless) return;
5457        int pid = Binder.getCallingPid();
5458        mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, pid));
5459    }
5460
5461    private void showStrictModeViolation(int arg, int pid) {
5462        final boolean on = arg != 0;
5463        synchronized(mWindowMap) {
5464            // Ignoring requests to enable the red border from clients
5465            // which aren't on screen.  (e.g. Broadcast Receivers in
5466            // the background..)
5467            if (on) {
5468                boolean isVisible = false;
5469                final int numDisplays = mDisplayContents.size();
5470                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5471                    final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
5472                    final int numWindows = windows.size();
5473                    for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
5474                        final WindowState ws = windows.get(winNdx);
5475                        if (ws.mSession.mPid == pid && ws.isVisibleLw()) {
5476                            isVisible = true;
5477                            break;
5478                        }
5479                    }
5480                }
5481                if (!isVisible) {
5482                    return;
5483                }
5484            }
5485
5486            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5487                    ">>> OPEN TRANSACTION showStrictModeViolation");
5488            SurfaceControl.openTransaction();
5489            try {
5490                // TODO(multi-display): support multiple displays
5491                if (mStrictModeFlash == null) {
5492                    mStrictModeFlash = new StrictModeFlash(
5493                            getDefaultDisplayContentLocked().getDisplay(), mFxSession);
5494                }
5495                mStrictModeFlash.setVisibility(on);
5496            } finally {
5497                SurfaceControl.closeTransaction();
5498                if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5499                        "<<< CLOSE TRANSACTION showStrictModeViolation");
5500            }
5501        }
5502    }
5503
5504    @Override
5505    public void setStrictModeVisualIndicatorPreference(String value) {
5506        SystemProperties.set(StrictMode.VISUAL_PROPERTY, value);
5507    }
5508
5509    /**
5510     * Takes a snapshot of the screen.  In landscape mode this grabs the whole screen.
5511     * In portrait mode, it grabs the upper region of the screen based on the vertical dimension
5512     * of the target image.
5513     *
5514     * @param displayId the Display to take a screenshot of.
5515     * @param width the width of the target bitmap
5516     * @param height the height of the target bitmap
5517     * @param force565 if true the returned bitmap will be RGB_565, otherwise it
5518     *                 will be the same config as the surface
5519     */
5520    @Override
5521    public Bitmap screenshotApplications(IBinder appToken, int displayId, int width,
5522            int height, boolean force565) {
5523        if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
5524                "screenshotApplications()")) {
5525            throw new SecurityException("Requires READ_FRAME_BUFFER permission");
5526        }
5527
5528        Bitmap rawss = null;
5529
5530        int maxLayer = 0;
5531        final Rect frame = new Rect();
5532
5533        float scale = 0;
5534        int dw, dh;
5535        int rot = Surface.ROTATION_0;
5536
5537        boolean screenshotReady;
5538        int minLayer;
5539        if (appToken == null) {
5540            screenshotReady = true;
5541            minLayer = 0;
5542        } else {
5543            screenshotReady = false;
5544            minLayer = Integer.MAX_VALUE;
5545        }
5546
5547        int retryCount = 0;
5548        WindowState appWin = null;
5549
5550        do {
5551            if (retryCount++ > 0) {
5552                try {
5553                    Thread.sleep(100);
5554                } catch (InterruptedException e) {
5555                }
5556            }
5557            synchronized(mWindowMap) {
5558                final DisplayContent displayContent = getDisplayContentLocked(displayId);
5559                if (displayContent == null) {
5560                    return null;
5561                }
5562                final DisplayInfo displayInfo = displayContent.getDisplayInfo();
5563                dw = displayInfo.logicalWidth;
5564                dh = displayInfo.logicalHeight;
5565
5566                int aboveAppLayer = mPolicy.windowTypeToLayerLw(TYPE_APPLICATION)
5567                        * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
5568                aboveAppLayer += TYPE_LAYER_MULTIPLIER;
5569
5570                boolean isImeTarget = mInputMethodTarget != null
5571                        && mInputMethodTarget.mAppToken != null
5572                        && mInputMethodTarget.mAppToken.appToken != null
5573                        && mInputMethodTarget.mAppToken.appToken.asBinder() == appToken;
5574
5575                // Figure out the part of the screen that is actually the app.
5576                boolean including = false;
5577                appWin = null;
5578                final WindowList windows = displayContent.getWindowList();
5579                final Rect stackBounds = new Rect();
5580                for (int i = windows.size() - 1; i >= 0; i--) {
5581                    WindowState ws = windows.get(i);
5582                    if (!ws.mHasSurface) {
5583                        continue;
5584                    }
5585                    if (ws.mLayer >= aboveAppLayer) {
5586                        continue;
5587                    }
5588                    // When we will skip windows: when we are not including
5589                    // ones behind a window we didn't skip, and we are actually
5590                    // taking a screenshot of a specific app.
5591                    if (!including && appToken != null) {
5592                        // Also, we can possibly skip this window if it is not
5593                        // an IME target or the application for the screenshot
5594                        // is not the current IME target.
5595                        if (!ws.mIsImWindow || !isImeTarget) {
5596                            // And finally, this window is of no interest if it
5597                            // is not associated with the screenshot app.
5598                            if (ws.mAppToken == null || ws.mAppToken.token != appToken) {
5599                                continue;
5600                            }
5601                            appWin = ws;
5602                            stackBounds.set(ws.getStackBounds());
5603                        }
5604                    }
5605
5606                    // We keep on including windows until we go past a full-screen
5607                    // window.
5608                    boolean fullscreen = ws.isFullscreen(dw, dh);
5609                    including = !ws.mIsImWindow && !fullscreen;
5610
5611                    final WindowStateAnimator winAnim = ws.mWinAnimator;
5612                    if (maxLayer < winAnim.mSurfaceLayer) {
5613                        maxLayer = winAnim.mSurfaceLayer;
5614                    }
5615                    if (minLayer > winAnim.mSurfaceLayer) {
5616                        minLayer = winAnim.mSurfaceLayer;
5617                    }
5618
5619                    // Don't include wallpaper in bounds calculation
5620                    if (!ws.mIsWallpaper) {
5621                        final Rect wf = ws.mFrame;
5622                        final Rect cr = ws.mContentInsets;
5623                        int left = wf.left + cr.left;
5624                        int top = wf.top + cr.top;
5625                        int right = wf.right - cr.right;
5626                        int bottom = wf.bottom - cr.bottom;
5627                        frame.union(left, top, right, bottom);
5628                        frame.intersect(stackBounds);
5629                    }
5630
5631                    if (ws.mAppToken != null && ws.mAppToken.token == appToken &&
5632                            ws.isDisplayedLw()) {
5633                        screenshotReady = true;
5634                    }
5635
5636                    if (fullscreen) {
5637                        // No point in continuing down through windows.
5638                        break;
5639                    }
5640                }
5641
5642                if (appToken != null && appWin == null) {
5643                    // Can't find a window to snapshot.
5644                    if (DEBUG_SCREENSHOT) Slog.i(TAG,
5645                            "Screenshot: Couldn't find a surface matching " + appToken);
5646                    return null;
5647                }
5648                if (!screenshotReady) {
5649                    // Delay and hope that window gets drawn.
5650                    if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot: No image ready for " + appToken
5651                            + ", " + appWin + " drawState=" + appWin.mWinAnimator.mDrawState);
5652                    continue;
5653                }
5654
5655                // Constrain frame to the screen size.
5656                frame.intersect(0, 0, dw, dh);
5657
5658                if (frame.isEmpty() || maxLayer == 0) {
5659                    if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken
5660                            + ": returning null frame=" + frame.toShortString() + " maxLayer="
5661                            + maxLayer);
5662                    return null;
5663                }
5664
5665                // The screenshot API does not apply the current screen rotation.
5666                rot = getDefaultDisplayContentLocked().getDisplay().getRotation();
5667                int fw = frame.width();
5668                int fh = frame.height();
5669
5670                // Constrain thumbnail to smaller of screen width or height. Assumes aspect
5671                // of thumbnail is the same as the screen (in landscape) or square.
5672                scale = Math.max(width / (float) fw, height / (float) fh);
5673                /*
5674                float targetWidthScale = width / (float) fw;
5675                float targetHeightScale = height / (float) fh;
5676                if (fw <= fh) {
5677                    scale = targetWidthScale;
5678                    // If aspect of thumbnail is the same as the screen (in landscape),
5679                    // select the slightly larger value so we fill the entire bitmap
5680                    if (targetHeightScale > scale && (int) (targetHeightScale * fw) == width) {
5681                        scale = targetHeightScale;
5682                    }
5683                } else {
5684                    scale = targetHeightScale;
5685                    // If aspect of thumbnail is the same as the screen (in landscape),
5686                    // select the slightly larger value so we fill the entire bitmap
5687                    if (targetWidthScale > scale && (int) (targetWidthScale * fh) == height) {
5688                        scale = targetWidthScale;
5689                    }
5690                }
5691                */
5692
5693                // The screen shot will contain the entire screen.
5694                dw = (int)(dw*scale);
5695                dh = (int)(dh*scale);
5696                if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
5697                    int tmp = dw;
5698                    dw = dh;
5699                    dh = tmp;
5700                    rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90;
5701                }
5702                if (DEBUG_SCREENSHOT) {
5703                    Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to "
5704                            + maxLayer + " appToken=" + appToken);
5705                    for (int i = 0; i < windows.size(); i++) {
5706                        WindowState win = windows.get(i);
5707                        Slog.i(TAG, win + ": " + win.mLayer
5708                                + " animLayer=" + win.mWinAnimator.mAnimLayer
5709                                + " surfaceLayer=" + win.mWinAnimator.mSurfaceLayer);
5710                    }
5711                }
5712                rawss = SurfaceControl.screenshot(dw, dh, minLayer, maxLayer);
5713            }
5714        } while (!screenshotReady && retryCount <= MAX_SCREENSHOT_RETRIES);
5715        if (retryCount > MAX_SCREENSHOT_RETRIES)  Slog.i(TAG, "Screenshot max retries " +
5716                retryCount + " of " + appToken + " appWin=" + (appWin == null ?
5717                        "null" : (appWin + " drawState=" + appWin.mWinAnimator.mDrawState)));
5718
5719        if (rawss == null) {
5720            Slog.w(TAG, "Screenshot failure taking screenshot for (" + dw + "x" + dh
5721                    + ") to layer " + maxLayer);
5722            return null;
5723        }
5724
5725        Bitmap bm = Bitmap.createBitmap(width, height, force565 ? Config.RGB_565 : rawss.getConfig());
5726        frame.scale(scale);
5727        Matrix matrix = new Matrix();
5728        ScreenRotationAnimation.createRotationMatrix(rot, dw, dh, matrix);
5729        // TODO: Test for RTL vs. LTR and use frame.right-width instead of -frame.left
5730        matrix.postTranslate(-FloatMath.ceil(frame.left), -FloatMath.ceil(frame.top));
5731        Canvas canvas = new Canvas(bm);
5732        canvas.drawColor(0xFF000000);
5733        canvas.drawBitmap(rawss, matrix, null);
5734        canvas.setBitmap(null);
5735
5736        if (true || DEBUG_SCREENSHOT) {
5737            // TEST IF IT's ALL BLACK
5738            int[] buffer = new int[bm.getWidth() * bm.getHeight()];
5739            bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight());
5740            boolean allBlack = true;
5741            final int firstColor = buffer[0];
5742            for (int i = 0; i < buffer.length; i++) {
5743                if (buffer[i] != firstColor) {
5744                    allBlack = false;
5745                    break;
5746                }
5747            }
5748            if (allBlack) {
5749                Slog.i(TAG, "Screenshot " + appWin + " was monochrome(" +
5750                        Integer.toHexString(firstColor) + ")! mSurfaceLayer=" +
5751                        (appWin != null ? appWin.mWinAnimator.mSurfaceLayer : "null") +
5752                        " minLayer=" + minLayer + " maxLayer=" + maxLayer);
5753            }
5754        }
5755
5756        rawss.recycle();
5757        return bm;
5758    }
5759
5760    /**
5761     * Freeze rotation changes.  (Enable "rotation lock".)
5762     * Persists across reboots.
5763     * @param rotation The desired rotation to freeze to, or -1 to use the
5764     * current rotation.
5765     */
5766    @Override
5767    public void freezeRotation(int rotation) {
5768        if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
5769                "freezeRotation()")) {
5770            throw new SecurityException("Requires SET_ORIENTATION permission");
5771        }
5772        if (rotation < -1 || rotation > Surface.ROTATION_270) {
5773            throw new IllegalArgumentException("Rotation argument must be -1 or a valid "
5774                    + "rotation constant.");
5775        }
5776
5777        if (DEBUG_ORIENTATION) Slog.v(TAG, "freezeRotation: mRotation=" + mRotation);
5778
5779        long origId = Binder.clearCallingIdentity();
5780        try {
5781            mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED,
5782                    rotation == -1 ? mRotation : rotation);
5783        } finally {
5784            Binder.restoreCallingIdentity(origId);
5785        }
5786
5787        updateRotationUnchecked(false, false);
5788    }
5789
5790    /**
5791     * Thaw rotation changes.  (Disable "rotation lock".)
5792     * Persists across reboots.
5793     */
5794    @Override
5795    public void thawRotation() {
5796        if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
5797                "thawRotation()")) {
5798            throw new SecurityException("Requires SET_ORIENTATION permission");
5799        }
5800
5801        if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation);
5802
5803        long origId = Binder.clearCallingIdentity();
5804        try {
5805            mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE,
5806                    777); // rot not used
5807        } finally {
5808            Binder.restoreCallingIdentity(origId);
5809        }
5810
5811        updateRotationUnchecked(false, false);
5812    }
5813
5814    /**
5815     * Recalculate the current rotation.
5816     *
5817     * Called by the window manager policy whenever the state of the system changes
5818     * such that the current rotation might need to be updated, such as when the
5819     * device is docked or rotated into a new posture.
5820     */
5821    @Override
5822    public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
5823        updateRotationUnchecked(alwaysSendConfiguration, forceRelayout);
5824    }
5825
5826    /**
5827     * Temporarily pauses rotation changes until resumed.
5828     *
5829     * This can be used to prevent rotation changes from occurring while the user is
5830     * performing certain operations, such as drag and drop.
5831     *
5832     * This call nests and must be matched by an equal number of calls to
5833     * {@link #resumeRotationLocked}.
5834     */
5835    void pauseRotationLocked() {
5836        mDeferredRotationPauseCount += 1;
5837    }
5838
5839    /**
5840     * Resumes normal rotation changes after being paused.
5841     */
5842    void resumeRotationLocked() {
5843        if (mDeferredRotationPauseCount > 0) {
5844            mDeferredRotationPauseCount -= 1;
5845            if (mDeferredRotationPauseCount == 0) {
5846                boolean changed = updateRotationUncheckedLocked(false);
5847                if (changed) {
5848                    mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
5849                }
5850            }
5851        }
5852    }
5853
5854    public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) {
5855        if(DEBUG_ORIENTATION) Slog.v(TAG, "updateRotationUnchecked("
5856                   + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")");
5857
5858        long origId = Binder.clearCallingIdentity();
5859        boolean changed;
5860        synchronized(mWindowMap) {
5861            changed = updateRotationUncheckedLocked(false);
5862            if (!changed || forceRelayout) {
5863                getDefaultDisplayContentLocked().layoutNeeded = true;
5864                performLayoutAndPlaceSurfacesLocked();
5865            }
5866        }
5867
5868        if (changed || alwaysSendConfiguration) {
5869            sendNewConfiguration();
5870        }
5871
5872        Binder.restoreCallingIdentity(origId);
5873    }
5874
5875    // TODO(multidisplay): Rotate any display?
5876    /**
5877     * Updates the current rotation.
5878     *
5879     * Returns true if the rotation has been changed.  In this case YOU
5880     * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN.
5881     */
5882    public boolean updateRotationUncheckedLocked(boolean inTransaction) {
5883        if (mDeferredRotationPauseCount > 0) {
5884            // Rotation updates have been paused temporarily.  Defer the update until
5885            // updates have been resumed.
5886            if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, rotation is paused.");
5887            return false;
5888        }
5889
5890        ScreenRotationAnimation screenRotationAnimation =
5891                mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
5892        if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
5893            // Rotation updates cannot be performed while the previous rotation change
5894            // animation is still in progress.  Skip this update.  We will try updating
5895            // again after the animation is finished and the display is unfrozen.
5896            if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, animation in progress.");
5897            return false;
5898        }
5899
5900        if (!mDisplayEnabled) {
5901            // No point choosing a rotation if the display is not enabled.
5902            if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, display is not enabled.");
5903            return false;
5904        }
5905
5906        // TODO: Implement forced rotation changes.
5907        //       Set mAltOrientation to indicate that the application is receiving
5908        //       an orientation that has different metrics than it expected.
5909        //       eg. Portrait instead of Landscape.
5910
5911        int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation);
5912        boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw(
5913                mForcedAppOrientation, rotation);
5914
5915        if (DEBUG_ORIENTATION) {
5916            Slog.v(TAG, "Application requested orientation "
5917                    + mForcedAppOrientation + ", got rotation " + rotation
5918                    + " which has " + (altOrientation ? "incompatible" : "compatible")
5919                    + " metrics");
5920        }
5921
5922        if (mRotation == rotation && mAltOrientation == altOrientation) {
5923            // No change.
5924            return false;
5925        }
5926
5927        if (DEBUG_ORIENTATION) {
5928            Slog.v(TAG,
5929                "Rotation changed to " + rotation + (altOrientation ? " (alt)" : "")
5930                + " from " + mRotation + (mAltOrientation ? " (alt)" : "")
5931                + ", forceApp=" + mForcedAppOrientation);
5932        }
5933
5934        mRotation = rotation;
5935        mAltOrientation = altOrientation;
5936        mPolicy.setRotationLw(mRotation);
5937
5938        mWindowsFreezingScreen = true;
5939        mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
5940        mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION);
5941        mWaitingForConfig = true;
5942        final DisplayContent displayContent = getDefaultDisplayContentLocked();
5943        displayContent.layoutNeeded = true;
5944        final int[] anim = new int[2];
5945        if (displayContent.isDimming()) {
5946            anim[0] = anim[1] = 0;
5947        } else {
5948            mPolicy.selectRotationAnimationLw(anim);
5949        }
5950        startFreezingDisplayLocked(inTransaction, anim[0], anim[1]);
5951        // startFreezingDisplayLocked can reset the ScreenRotationAnimation.
5952        screenRotationAnimation =
5953                mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
5954
5955        // We need to update our screen size information to match the new
5956        // rotation.  Note that this is redundant with the later call to
5957        // sendNewConfiguration() that must be called after this function
5958        // returns...  however we need to do the screen size part of that
5959        // before then so we have the correct size to use when initializing
5960        // the rotation animation for the new rotation.
5961        computeScreenConfigurationLocked(null);
5962
5963        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
5964        if (!inTransaction) {
5965            if (SHOW_TRANSACTIONS) {
5966                Slog.i(TAG, ">>> OPEN TRANSACTION setRotationUnchecked");
5967            }
5968            SurfaceControl.openTransaction();
5969        }
5970        try {
5971            // NOTE: We disable the rotation in the emulator because
5972            //       it doesn't support hardware OpenGL emulation yet.
5973            if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
5974                    && screenRotationAnimation.hasScreenshot()) {
5975                if (screenRotationAnimation.setRotationInTransaction(
5976                        rotation, mFxSession,
5977                        MAX_ANIMATION_DURATION, mTransitionAnimationScale,
5978                        displayInfo.logicalWidth, displayInfo.logicalHeight)) {
5979                    scheduleAnimationLocked();
5980                }
5981            }
5982
5983            mDisplayManagerService.performTraversalInTransactionFromWindowManager();
5984        } finally {
5985            if (!inTransaction) {
5986                SurfaceControl.closeTransaction();
5987                if (SHOW_LIGHT_TRANSACTIONS) {
5988                    Slog.i(TAG, "<<< CLOSE TRANSACTION setRotationUnchecked");
5989                }
5990            }
5991        }
5992
5993        final WindowList windows = displayContent.getWindowList();
5994        for (int i = windows.size() - 1; i >= 0; i--) {
5995            WindowState w = windows.get(i);
5996            if (w.mHasSurface) {
5997                if (DEBUG_ORIENTATION) Slog.v(TAG, "Set mOrientationChanging of " + w);
5998                w.mOrientationChanging = true;
5999                mInnerFields.mOrientationChangeComplete = false;
6000            }
6001            w.mLastFreezeDuration = 0;
6002        }
6003
6004        for (int i=mRotationWatchers.size()-1; i>=0; i--) {
6005            try {
6006                mRotationWatchers.get(i).onRotationChanged(rotation);
6007            } catch (RemoteException e) {
6008            }
6009        }
6010
6011        //TODO (multidisplay): Magnification is supported only for the default display.
6012        if (mDisplayMagnifier != null
6013                && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) {
6014            mDisplayMagnifier.onRotationChangedLocked(getDefaultDisplayContentLocked(), rotation);
6015        }
6016
6017        return true;
6018    }
6019
6020    @Override
6021    public int getRotation() {
6022        return mRotation;
6023    }
6024
6025    @Override
6026    public boolean isRotationFrozen() {
6027        return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED;
6028    }
6029
6030    @Override
6031    public int watchRotation(IRotationWatcher watcher) {
6032        final IBinder watcherBinder = watcher.asBinder();
6033        IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
6034            @Override
6035            public void binderDied() {
6036                synchronized (mWindowMap) {
6037                    for (int i=0; i<mRotationWatchers.size(); i++) {
6038                        if (watcherBinder == mRotationWatchers.get(i).asBinder()) {
6039                            IRotationWatcher removed = mRotationWatchers.remove(i);
6040                            if (removed != null) {
6041                                removed.asBinder().unlinkToDeath(this, 0);
6042                            }
6043                            i--;
6044                        }
6045                    }
6046                }
6047            }
6048        };
6049
6050        synchronized (mWindowMap) {
6051            try {
6052                watcher.asBinder().linkToDeath(dr, 0);
6053                mRotationWatchers.add(watcher);
6054            } catch (RemoteException e) {
6055                // Client died, no cleanup needed.
6056            }
6057
6058            return mRotation;
6059        }
6060    }
6061
6062    @Override
6063    public void removeRotationWatcher(IRotationWatcher watcher) {
6064        final IBinder watcherBinder = watcher.asBinder();
6065        synchronized (mWindowMap) {
6066            for (int i=0; i<mRotationWatchers.size(); i++) {
6067                if (watcherBinder == mRotationWatchers.get(i).asBinder()) {
6068                    mRotationWatchers.remove(i);
6069                    i--;
6070                }
6071            }
6072        }
6073    }
6074
6075    /**
6076     * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact
6077     * theme attribute) on devices that feature a physical options menu key attempt to position
6078     * their menu panel window along the edge of the screen nearest the physical menu key.
6079     * This lowers the travel distance between invoking the menu panel and selecting
6080     * a menu option.
6081     *
6082     * This method helps control where that menu is placed. Its current implementation makes
6083     * assumptions about the menu key and its relationship to the screen based on whether
6084     * the device's natural orientation is portrait (width < height) or landscape.
6085     *
6086     * The menu key is assumed to be located along the bottom edge of natural-portrait
6087     * devices and along the right edge of natural-landscape devices. If these assumptions
6088     * do not hold for the target device, this method should be changed to reflect that.
6089     *
6090     * @return A {@link Gravity} value for placing the options menu window
6091     */
6092    @Override
6093    public int getPreferredOptionsPanelGravity() {
6094        synchronized (mWindowMap) {
6095            final int rotation = getRotation();
6096
6097            // TODO(multidisplay): Assume that such devices physical keys are on the main screen.
6098            final DisplayContent displayContent = getDefaultDisplayContentLocked();
6099            if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) {
6100                // On devices with a natural orientation of portrait
6101                switch (rotation) {
6102                    default:
6103                    case Surface.ROTATION_0:
6104                        return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6105                    case Surface.ROTATION_90:
6106                        return Gravity.RIGHT | Gravity.BOTTOM;
6107                    case Surface.ROTATION_180:
6108                        return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6109                    case Surface.ROTATION_270:
6110                        return Gravity.START | Gravity.BOTTOM;
6111                }
6112            }
6113
6114            // On devices with a natural orientation of landscape
6115            switch (rotation) {
6116                default:
6117                case Surface.ROTATION_0:
6118                    return Gravity.RIGHT | Gravity.BOTTOM;
6119                case Surface.ROTATION_90:
6120                    return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6121                case Surface.ROTATION_180:
6122                    return Gravity.START | Gravity.BOTTOM;
6123                case Surface.ROTATION_270:
6124                    return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6125            }
6126        }
6127    }
6128
6129    /**
6130     * Starts the view server on the specified port.
6131     *
6132     * @param port The port to listener to.
6133     *
6134     * @return True if the server was successfully started, false otherwise.
6135     *
6136     * @see com.android.server.wm.ViewServer
6137     * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT
6138     */
6139    @Override
6140    public boolean startViewServer(int port) {
6141        if (isSystemSecure()) {
6142            return false;
6143        }
6144
6145        if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) {
6146            return false;
6147        }
6148
6149        if (port < 1024) {
6150            return false;
6151        }
6152
6153        if (mViewServer != null) {
6154            if (!mViewServer.isRunning()) {
6155                try {
6156                    return mViewServer.start();
6157                } catch (IOException e) {
6158                    Slog.w(TAG, "View server did not start");
6159                }
6160            }
6161            return false;
6162        }
6163
6164        try {
6165            mViewServer = new ViewServer(this, port);
6166            return mViewServer.start();
6167        } catch (IOException e) {
6168            Slog.w(TAG, "View server did not start");
6169        }
6170        return false;
6171    }
6172
6173    private boolean isSystemSecure() {
6174        return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) &&
6175                "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
6176    }
6177
6178    /**
6179     * Stops the view server if it exists.
6180     *
6181     * @return True if the server stopped, false if it wasn't started or
6182     *         couldn't be stopped.
6183     *
6184     * @see com.android.server.wm.ViewServer
6185     */
6186    @Override
6187    public boolean stopViewServer() {
6188        if (isSystemSecure()) {
6189            return false;
6190        }
6191
6192        if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) {
6193            return false;
6194        }
6195
6196        if (mViewServer != null) {
6197            return mViewServer.stop();
6198        }
6199        return false;
6200    }
6201
6202    /**
6203     * Indicates whether the view server is running.
6204     *
6205     * @return True if the server is running, false otherwise.
6206     *
6207     * @see com.android.server.wm.ViewServer
6208     */
6209    @Override
6210    public boolean isViewServerRunning() {
6211        if (isSystemSecure()) {
6212            return false;
6213        }
6214
6215        if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) {
6216            return false;
6217        }
6218
6219        return mViewServer != null && mViewServer.isRunning();
6220    }
6221
6222    /**
6223     * Lists all availble windows in the system. The listing is written in the
6224     * specified Socket's output stream with the following syntax:
6225     * windowHashCodeInHexadecimal windowName
6226     * Each line of the ouput represents a different window.
6227     *
6228     * @param client The remote client to send the listing to.
6229     * @return False if an error occured, true otherwise.
6230     */
6231    boolean viewServerListWindows(Socket client) {
6232        if (isSystemSecure()) {
6233            return false;
6234        }
6235
6236        boolean result = true;
6237
6238        WindowList windows = new WindowList();
6239        synchronized (mWindowMap) {
6240            //noinspection unchecked
6241            final int numDisplays = mDisplayContents.size();
6242            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
6243                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
6244                windows.addAll(displayContent.getWindowList());
6245            }
6246        }
6247
6248        BufferedWriter out = null;
6249
6250        // Any uncaught exception will crash the system process
6251        try {
6252            OutputStream clientStream = client.getOutputStream();
6253            out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
6254
6255            final int count = windows.size();
6256            for (int i = 0; i < count; i++) {
6257                final WindowState w = windows.get(i);
6258                out.write(Integer.toHexString(System.identityHashCode(w)));
6259                out.write(' ');
6260                out.append(w.mAttrs.getTitle());
6261                out.write('\n');
6262            }
6263
6264            out.write("DONE.\n");
6265            out.flush();
6266        } catch (Exception e) {
6267            result = false;
6268        } finally {
6269            if (out != null) {
6270                try {
6271                    out.close();
6272                } catch (IOException e) {
6273                    result = false;
6274                }
6275            }
6276        }
6277
6278        return result;
6279    }
6280
6281    // TODO(multidisplay): Extend to multiple displays.
6282    /**
6283     * Returns the focused window in the following format:
6284     * windowHashCodeInHexadecimal windowName
6285     *
6286     * @param client The remote client to send the listing to.
6287     * @return False if an error occurred, true otherwise.
6288     */
6289    boolean viewServerGetFocusedWindow(Socket client) {
6290        if (isSystemSecure()) {
6291            return false;
6292        }
6293
6294        boolean result = true;
6295
6296        WindowState focusedWindow = getFocusedWindow();
6297
6298        BufferedWriter out = null;
6299
6300        // Any uncaught exception will crash the system process
6301        try {
6302            OutputStream clientStream = client.getOutputStream();
6303            out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
6304
6305            if(focusedWindow != null) {
6306                out.write(Integer.toHexString(System.identityHashCode(focusedWindow)));
6307                out.write(' ');
6308                out.append(focusedWindow.mAttrs.getTitle());
6309            }
6310            out.write('\n');
6311            out.flush();
6312        } catch (Exception e) {
6313            result = false;
6314        } finally {
6315            if (out != null) {
6316                try {
6317                    out.close();
6318                } catch (IOException e) {
6319                    result = false;
6320                }
6321            }
6322        }
6323
6324        return result;
6325    }
6326
6327    /**
6328     * Sends a command to a target window. The result of the command, if any, will be
6329     * written in the output stream of the specified socket.
6330     *
6331     * The parameters must follow this syntax:
6332     * windowHashcode extra
6333     *
6334     * Where XX is the length in characeters of the windowTitle.
6335     *
6336     * The first parameter is the target window. The window with the specified hashcode
6337     * will be the target. If no target can be found, nothing happens. The extra parameters
6338     * will be delivered to the target window and as parameters to the command itself.
6339     *
6340     * @param client The remote client to sent the result, if any, to.
6341     * @param command The command to execute.
6342     * @param parameters The command parameters.
6343     *
6344     * @return True if the command was successfully delivered, false otherwise. This does
6345     *         not indicate whether the command itself was successful.
6346     */
6347    boolean viewServerWindowCommand(Socket client, String command, String parameters) {
6348        if (isSystemSecure()) {
6349            return false;
6350        }
6351
6352        boolean success = true;
6353        Parcel data = null;
6354        Parcel reply = null;
6355
6356        BufferedWriter out = null;
6357
6358        // Any uncaught exception will crash the system process
6359        try {
6360            // Find the hashcode of the window
6361            int index = parameters.indexOf(' ');
6362            if (index == -1) {
6363                index = parameters.length();
6364            }
6365            final String code = parameters.substring(0, index);
6366            int hashCode = (int) Long.parseLong(code, 16);
6367
6368            // Extract the command's parameter after the window description
6369            if (index < parameters.length()) {
6370                parameters = parameters.substring(index + 1);
6371            } else {
6372                parameters = "";
6373            }
6374
6375            final WindowState window = findWindow(hashCode);
6376            if (window == null) {
6377                return false;
6378            }
6379
6380            data = Parcel.obtain();
6381            data.writeInterfaceToken("android.view.IWindow");
6382            data.writeString(command);
6383            data.writeString(parameters);
6384            data.writeInt(1);
6385            ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0);
6386
6387            reply = Parcel.obtain();
6388
6389            final IBinder binder = window.mClient.asBinder();
6390            // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER
6391            binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
6392
6393            reply.readException();
6394
6395            if (!client.isOutputShutdown()) {
6396                out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
6397                out.write("DONE\n");
6398                out.flush();
6399            }
6400
6401        } catch (Exception e) {
6402            Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e);
6403            success = false;
6404        } finally {
6405            if (data != null) {
6406                data.recycle();
6407            }
6408            if (reply != null) {
6409                reply.recycle();
6410            }
6411            if (out != null) {
6412                try {
6413                    out.close();
6414                } catch (IOException e) {
6415
6416                }
6417            }
6418        }
6419
6420        return success;
6421    }
6422
6423    public void addWindowChangeListener(WindowChangeListener listener) {
6424        synchronized(mWindowMap) {
6425            mWindowChangeListeners.add(listener);
6426        }
6427    }
6428
6429    public void removeWindowChangeListener(WindowChangeListener listener) {
6430        synchronized(mWindowMap) {
6431            mWindowChangeListeners.remove(listener);
6432        }
6433    }
6434
6435    private void notifyWindowsChanged() {
6436        WindowChangeListener[] windowChangeListeners;
6437        synchronized(mWindowMap) {
6438            if(mWindowChangeListeners.isEmpty()) {
6439                return;
6440            }
6441            windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
6442            windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
6443        }
6444        int N = windowChangeListeners.length;
6445        for(int i = 0; i < N; i++) {
6446            windowChangeListeners[i].windowsChanged();
6447        }
6448    }
6449
6450    private void notifyFocusChanged() {
6451        WindowChangeListener[] windowChangeListeners;
6452        synchronized(mWindowMap) {
6453            if(mWindowChangeListeners.isEmpty()) {
6454                return;
6455            }
6456            windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
6457            windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
6458        }
6459        int N = windowChangeListeners.length;
6460        for(int i = 0; i < N; i++) {
6461            windowChangeListeners[i].focusChanged();
6462        }
6463    }
6464
6465    private WindowState findWindow(int hashCode) {
6466        if (hashCode == -1) {
6467            // TODO(multidisplay): Extend to multiple displays.
6468            return getFocusedWindow();
6469        }
6470
6471        synchronized (mWindowMap) {
6472            final int numDisplays = mDisplayContents.size();
6473            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
6474                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
6475                final int numWindows = windows.size();
6476                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
6477                    final WindowState w = windows.get(winNdx);
6478                    if (System.identityHashCode(w) == hashCode) {
6479                        return w;
6480                    }
6481                }
6482            }
6483        }
6484
6485        return null;
6486    }
6487
6488    /*
6489     * Instruct the Activity Manager to fetch the current configuration and broadcast
6490     * that to config-changed listeners if appropriate.
6491     */
6492    void sendNewConfiguration() {
6493        try {
6494            mActivityManager.updateConfiguration(null);
6495        } catch (RemoteException e) {
6496        }
6497    }
6498
6499    public Configuration computeNewConfiguration() {
6500        synchronized (mWindowMap) {
6501            Configuration config = computeNewConfigurationLocked();
6502            if (config == null && mWaitingForConfig) {
6503                // Nothing changed but we are waiting for something... stop that!
6504                mWaitingForConfig = false;
6505                mLastFinishedFreezeSource = "new-config";
6506                performLayoutAndPlaceSurfacesLocked();
6507            }
6508            return config;
6509        }
6510    }
6511
6512    Configuration computeNewConfigurationLocked() {
6513        Configuration config = new Configuration();
6514        config.fontScale = 0;
6515        if (!computeScreenConfigurationLocked(config)) {
6516            return null;
6517        }
6518        return config;
6519    }
6520
6521    private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int dw, int dh) {
6522        // TODO: Multidisplay: for now only use with default display.
6523        final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation);
6524        if (width < displayInfo.smallestNominalAppWidth) {
6525            displayInfo.smallestNominalAppWidth = width;
6526        }
6527        if (width > displayInfo.largestNominalAppWidth) {
6528            displayInfo.largestNominalAppWidth = width;
6529        }
6530        final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation);
6531        if (height < displayInfo.smallestNominalAppHeight) {
6532            displayInfo.smallestNominalAppHeight = height;
6533        }
6534        if (height > displayInfo.largestNominalAppHeight) {
6535            displayInfo.largestNominalAppHeight = height;
6536        }
6537    }
6538
6539    private int reduceConfigLayout(int curLayout, int rotation, float density,
6540            int dw, int dh) {
6541        // TODO: Multidisplay: for now only use with default display.
6542        // Get the app screen size at this rotation.
6543        int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation);
6544        int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation);
6545
6546        // Compute the screen layout size class for this rotation.
6547        int longSize = w;
6548        int shortSize = h;
6549        if (longSize < shortSize) {
6550            int tmp = longSize;
6551            longSize = shortSize;
6552            shortSize = tmp;
6553        }
6554        longSize = (int)(longSize/density);
6555        shortSize = (int)(shortSize/density);
6556        return Configuration.reduceScreenLayout(curLayout, longSize, shortSize);
6557    }
6558
6559    private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated,
6560                  int dw, int dh, float density, Configuration outConfig) {
6561        // TODO: Multidisplay: for now only use with default display.
6562
6563        // We need to determine the smallest width that will occur under normal
6564        // operation.  To this, start with the base screen size and compute the
6565        // width under the different possible rotations.  We need to un-rotate
6566        // the current screen dimensions before doing this.
6567        int unrotDw, unrotDh;
6568        if (rotated) {
6569            unrotDw = dh;
6570            unrotDh = dw;
6571        } else {
6572            unrotDw = dw;
6573            unrotDh = dh;
6574        }
6575        displayInfo.smallestNominalAppWidth = 1<<30;
6576        displayInfo.smallestNominalAppHeight = 1<<30;
6577        displayInfo.largestNominalAppWidth = 0;
6578        displayInfo.largestNominalAppHeight = 0;
6579        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, unrotDw, unrotDh);
6580        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, unrotDh, unrotDw);
6581        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, unrotDw, unrotDh);
6582        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, unrotDh, unrotDw);
6583        int sl = Configuration.resetScreenLayout(outConfig.screenLayout);
6584        sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh);
6585        sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw);
6586        sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh);
6587        sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw);
6588        outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density);
6589        outConfig.screenLayout = sl;
6590    }
6591
6592    private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm,
6593            int dw, int dh) {
6594        // TODO: Multidisplay: for now only use with default display.
6595        dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation);
6596        dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation);
6597        float scale = CompatibilityInfo.computeCompatibleScaling(dm, null);
6598        int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f);
6599        if (curSize == 0 || size < curSize) {
6600            curSize = size;
6601        }
6602        return curSize;
6603    }
6604
6605    private int computeCompatSmallestWidth(boolean rotated, DisplayMetrics dm, int dw, int dh) {
6606        // TODO: Multidisplay: for now only use with default display.
6607        mTmpDisplayMetrics.setTo(dm);
6608        final DisplayMetrics tmpDm = mTmpDisplayMetrics;
6609        final int unrotDw, unrotDh;
6610        if (rotated) {
6611            unrotDw = dh;
6612            unrotDh = dw;
6613        } else {
6614            unrotDw = dw;
6615            unrotDh = dh;
6616        }
6617        int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, tmpDm, unrotDw, unrotDh);
6618        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, tmpDm, unrotDh, unrotDw);
6619        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, tmpDm, unrotDw, unrotDh);
6620        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, tmpDm, unrotDh, unrotDw);
6621        return sw;
6622    }
6623
6624    boolean computeScreenConfigurationLocked(Configuration config) {
6625        if (!mDisplayReady) {
6626            return false;
6627        }
6628
6629        // TODO(multidisplay): For now, apply Configuration to main screen only.
6630        final DisplayContent displayContent = getDefaultDisplayContentLocked();
6631
6632        // Use the effective "visual" dimensions based on current rotation
6633        final boolean rotated = (mRotation == Surface.ROTATION_90
6634                || mRotation == Surface.ROTATION_270);
6635        final int realdw = rotated ?
6636                displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth;
6637        final int realdh = rotated ?
6638                displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight;
6639        int dw = realdw;
6640        int dh = realdh;
6641
6642        if (mAltOrientation) {
6643            if (realdw > realdh) {
6644                // Turn landscape into portrait.
6645                int maxw = (int)(realdh/1.3f);
6646                if (maxw < realdw) {
6647                    dw = maxw;
6648                }
6649            } else {
6650                // Turn portrait into landscape.
6651                int maxh = (int)(realdw/1.3f);
6652                if (maxh < realdh) {
6653                    dh = maxh;
6654                }
6655            }
6656        }
6657
6658        if (config != null) {
6659            config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT :
6660                    Configuration.ORIENTATION_LANDSCAPE;
6661        }
6662
6663        // Update application display metrics.
6664        final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation);
6665        final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation);
6666        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
6667        synchronized(displayContent.mDisplaySizeLock) {
6668            displayInfo.rotation = mRotation;
6669            displayInfo.logicalWidth = dw;
6670            displayInfo.logicalHeight = dh;
6671            displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity;
6672            displayInfo.appWidth = appWidth;
6673            displayInfo.appHeight = appHeight;
6674            displayInfo.getLogicalMetrics(mRealDisplayMetrics,
6675                    CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
6676            displayInfo.getAppMetrics(mDisplayMetrics);
6677            mDisplayManagerService.setDisplayInfoOverrideFromWindowManager(
6678                    displayContent.getDisplayId(), displayInfo);
6679        }
6680        if (false) {
6681            Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight);
6682        }
6683
6684        final DisplayMetrics dm = mDisplayMetrics;
6685        mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm,
6686                mCompatDisplayMetrics);
6687
6688        if (config != null) {
6689            config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation)
6690                    / dm.density);
6691            config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation)
6692                    / dm.density);
6693            computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, dm.density, config);
6694
6695            config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale);
6696            config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale);
6697            config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh);
6698            config.densityDpi = displayContent.mBaseDisplayDensity;
6699
6700            // Update the configuration based on available input devices, lid switch,
6701            // and platform configuration.
6702            config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
6703            config.keyboard = Configuration.KEYBOARD_NOKEYS;
6704            config.navigation = Configuration.NAVIGATION_NONAV;
6705
6706            int keyboardPresence = 0;
6707            int navigationPresence = 0;
6708            final InputDevice[] devices = mInputManager.getInputDevices();
6709            final int len = devices.length;
6710            for (int i = 0; i < len; i++) {
6711                InputDevice device = devices[i];
6712                if (!device.isVirtual()) {
6713                    final int sources = device.getSources();
6714                    final int presenceFlag = device.isExternal() ?
6715                            WindowManagerPolicy.PRESENCE_EXTERNAL :
6716                                    WindowManagerPolicy.PRESENCE_INTERNAL;
6717
6718                    if (mIsTouchDevice) {
6719                        if ((sources & InputDevice.SOURCE_TOUCHSCREEN) ==
6720                                InputDevice.SOURCE_TOUCHSCREEN) {
6721                            config.touchscreen = Configuration.TOUCHSCREEN_FINGER;
6722                        }
6723                    } else {
6724                        config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
6725                    }
6726
6727                    if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) {
6728                        config.navigation = Configuration.NAVIGATION_TRACKBALL;
6729                        navigationPresence |= presenceFlag;
6730                    } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD
6731                            && config.navigation == Configuration.NAVIGATION_NONAV) {
6732                        config.navigation = Configuration.NAVIGATION_DPAD;
6733                        navigationPresence |= presenceFlag;
6734                    }
6735
6736                    if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {
6737                        config.keyboard = Configuration.KEYBOARD_QWERTY;
6738                        keyboardPresence |= presenceFlag;
6739                    }
6740                }
6741            }
6742
6743            // Determine whether a hard keyboard is available and enabled.
6744            boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS;
6745            if (hardKeyboardAvailable != mHardKeyboardAvailable) {
6746                mHardKeyboardAvailable = hardKeyboardAvailable;
6747                mHardKeyboardEnabled = hardKeyboardAvailable;
6748                mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
6749                mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
6750            }
6751            if (!mHardKeyboardEnabled) {
6752                config.keyboard = Configuration.KEYBOARD_NOKEYS;
6753            }
6754
6755            // Let the policy update hidden states.
6756            config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
6757            config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
6758            config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO;
6759            mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence);
6760        }
6761
6762        return true;
6763    }
6764
6765    public boolean isHardKeyboardAvailable() {
6766        synchronized (mWindowMap) {
6767            return mHardKeyboardAvailable;
6768        }
6769    }
6770
6771    public boolean isHardKeyboardEnabled() {
6772        synchronized (mWindowMap) {
6773            return mHardKeyboardEnabled;
6774        }
6775    }
6776
6777    public void setHardKeyboardEnabled(boolean enabled) {
6778        synchronized (mWindowMap) {
6779            if (mHardKeyboardEnabled != enabled) {
6780                mHardKeyboardEnabled = enabled;
6781                mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
6782            }
6783        }
6784    }
6785
6786    public void setOnHardKeyboardStatusChangeListener(
6787            OnHardKeyboardStatusChangeListener listener) {
6788        synchronized (mWindowMap) {
6789            mHardKeyboardStatusChangeListener = listener;
6790        }
6791    }
6792
6793    void notifyHardKeyboardStatusChange() {
6794        final boolean available, enabled;
6795        final OnHardKeyboardStatusChangeListener listener;
6796        synchronized (mWindowMap) {
6797            listener = mHardKeyboardStatusChangeListener;
6798            available = mHardKeyboardAvailable;
6799            enabled = mHardKeyboardEnabled;
6800        }
6801        if (listener != null) {
6802            listener.onHardKeyboardStatusChange(available, enabled);
6803        }
6804    }
6805
6806    // -------------------------------------------------------------
6807    // Drag and drop
6808    // -------------------------------------------------------------
6809
6810    IBinder prepareDragSurface(IWindow window, SurfaceSession session,
6811            int flags, int width, int height, Surface outSurface) {
6812        if (DEBUG_DRAG) {
6813            Slog.d(TAG, "prepare drag surface: w=" + width + " h=" + height
6814                    + " flags=" + Integer.toHexString(flags) + " win=" + window
6815                    + " asbinder=" + window.asBinder());
6816        }
6817
6818        final int callerPid = Binder.getCallingPid();
6819        final long origId = Binder.clearCallingIdentity();
6820        IBinder token = null;
6821
6822        try {
6823            synchronized (mWindowMap) {
6824                try {
6825                    if (mDragState == null) {
6826                        // TODO(multi-display): support other displays
6827                        final DisplayContent displayContent = getDefaultDisplayContentLocked();
6828                        final Display display = displayContent.getDisplay();
6829                        SurfaceControl surface = new SurfaceControl(session, "drag surface",
6830                                width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
6831                        surface.setLayerStack(display.getLayerStack());
6832                        if (SHOW_TRANSACTIONS) Slog.i(TAG, "  DRAG "
6833                                + surface + ": CREATE");
6834                        outSurface.copyFrom(surface);
6835                        final IBinder winBinder = window.asBinder();
6836                        token = new Binder();
6837                        mDragState = new DragState(this, token, surface, /*flags*/ 0, winBinder);
6838                        token = mDragState.mToken = new Binder();
6839
6840                        // 5 second timeout for this window to actually begin the drag
6841                        mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder);
6842                        Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder);
6843                        mH.sendMessageDelayed(msg, 5000);
6844                    } else {
6845                        Slog.w(TAG, "Drag already in progress");
6846                    }
6847                } catch (OutOfResourcesException e) {
6848                    Slog.e(TAG, "Can't allocate drag surface w=" + width + " h=" + height, e);
6849                    if (mDragState != null) {
6850                        mDragState.reset();
6851                        mDragState = null;
6852                    }
6853                }
6854            }
6855        } finally {
6856            Binder.restoreCallingIdentity(origId);
6857        }
6858
6859        return token;
6860    }
6861
6862    // -------------------------------------------------------------
6863    // Input Events and Focus Management
6864    // -------------------------------------------------------------
6865
6866    final InputMonitor mInputMonitor = new InputMonitor(this);
6867    private boolean mEventDispatchingEnabled;
6868
6869    @Override
6870    public void pauseKeyDispatching(IBinder _token) {
6871        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
6872                "pauseKeyDispatching()")) {
6873            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
6874        }
6875
6876        synchronized (mWindowMap) {
6877            WindowToken token = mTokenMap.get(_token);
6878            if (token != null) {
6879                mInputMonitor.pauseDispatchingLw(token);
6880            }
6881        }
6882    }
6883
6884    @Override
6885    public void resumeKeyDispatching(IBinder _token) {
6886        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
6887                "resumeKeyDispatching()")) {
6888            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
6889        }
6890
6891        synchronized (mWindowMap) {
6892            WindowToken token = mTokenMap.get(_token);
6893            if (token != null) {
6894                mInputMonitor.resumeDispatchingLw(token);
6895            }
6896        }
6897    }
6898
6899    @Override
6900    public void setEventDispatching(boolean enabled) {
6901        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
6902                "setEventDispatching()")) {
6903            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
6904        }
6905
6906        synchronized (mWindowMap) {
6907            mEventDispatchingEnabled = enabled;
6908            if (mDisplayEnabled) {
6909                mInputMonitor.setEventDispatchingLw(enabled);
6910            }
6911            sendScreenStatusToClientsLocked();
6912        }
6913    }
6914
6915    @Override
6916    public IBinder getFocusedWindowToken() {
6917        if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO,
6918                "getFocusedWindowToken()")) {
6919            throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission.");
6920        }
6921        synchronized (mWindowMap) {
6922            WindowState windowState = getFocusedWindowLocked();
6923            if (windowState != null) {
6924                return windowState.mClient.asBinder();
6925            }
6926            return null;
6927        }
6928    }
6929
6930    private WindowState getFocusedWindow() {
6931        synchronized (mWindowMap) {
6932            return getFocusedWindowLocked();
6933        }
6934    }
6935
6936    private WindowState getFocusedWindowLocked() {
6937        return mCurrentFocus;
6938    }
6939
6940    public boolean detectSafeMode() {
6941        if (!mInputMonitor.waitForInputDevicesReady(
6942                INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) {
6943            Slog.w(TAG, "Devices still not ready after waiting "
6944                   + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS
6945                   + " milliseconds before attempting to detect safe mode.");
6946        }
6947
6948        int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
6949                KeyEvent.KEYCODE_MENU);
6950        int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S);
6951        int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD,
6952                KeyEvent.KEYCODE_DPAD_CENTER);
6953        int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL,
6954                InputManagerService.BTN_MOUSE);
6955        int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
6956                KeyEvent.KEYCODE_VOLUME_DOWN);
6957        mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0
6958                || volumeDownState > 0;
6959        try {
6960            if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0) {
6961                mSafeMode = true;
6962                SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, "");
6963            }
6964        } catch (IllegalArgumentException e) {
6965        }
6966        if (mSafeMode) {
6967            Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState
6968                    + " dpad=" + dpadState + " trackball=" + trackballState + ")");
6969        } else {
6970            Log.i(TAG, "SAFE MODE not enabled");
6971        }
6972        mPolicy.setSafeMode(mSafeMode);
6973        return mSafeMode;
6974    }
6975
6976    public void displayReady() {
6977        displayReady(Display.DEFAULT_DISPLAY);
6978
6979        synchronized(mWindowMap) {
6980            final DisplayContent displayContent = getDefaultDisplayContentLocked();
6981            readForcedDisplaySizeAndDensityLocked(displayContent);
6982            mDisplayReady = true;
6983        }
6984
6985        try {
6986            mActivityManager.updateConfiguration(null);
6987        } catch (RemoteException e) {
6988        }
6989
6990        synchronized(mWindowMap) {
6991            mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
6992                    PackageManager.FEATURE_TOUCHSCREEN);
6993            configureDisplayPolicyLocked(getDefaultDisplayContentLocked());
6994        }
6995
6996        try {
6997            mActivityManager.updateConfiguration(null);
6998        } catch (RemoteException e) {
6999        }
7000    }
7001
7002    private void displayReady(int displayId) {
7003        synchronized(mWindowMap) {
7004            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7005            if (displayContent != null) {
7006                mAnimator.addDisplayLocked(displayId);
7007                synchronized(displayContent.mDisplaySizeLock) {
7008                    // Bootstrap the default logical display from the display manager.
7009                    final DisplayInfo displayInfo = displayContent.getDisplayInfo();
7010                    DisplayInfo newDisplayInfo = mDisplayManagerService.getDisplayInfo(displayId);
7011                    if (newDisplayInfo != null) {
7012                        displayInfo.copyFrom(newDisplayInfo);
7013                    }
7014                    displayContent.mInitialDisplayWidth = displayInfo.logicalWidth;
7015                    displayContent.mInitialDisplayHeight = displayInfo.logicalHeight;
7016                    displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi;
7017                    displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth;
7018                    displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight;
7019                    displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity;
7020                    displayContent.mBaseDisplayRect.set(0, 0,
7021                            displayContent.mBaseDisplayWidth, displayContent.mBaseDisplayHeight);
7022                }
7023            }
7024        }
7025    }
7026
7027    public void systemReady() {
7028        mPolicy.systemReady();
7029    }
7030
7031    // TODO(multidisplay): Call isScreenOn for each display.
7032    private void sendScreenStatusToClientsLocked() {
7033        final boolean on = mPowerManager.isScreenOn();
7034        final int numDisplays = mDisplayContents.size();
7035        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
7036            final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
7037            final int numWindows = windows.size();
7038            for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
7039                try {
7040                    windows.get(winNdx).mClient.dispatchScreenState(on);
7041                } catch (RemoteException e) {
7042                    // Ignored
7043                }
7044            }
7045        }
7046    }
7047
7048    // -------------------------------------------------------------
7049    // Async Handler
7050    // -------------------------------------------------------------
7051
7052    final class H extends Handler {
7053        public static final int REPORT_FOCUS_CHANGE = 2;
7054        public static final int REPORT_LOSING_FOCUS = 3;
7055        public static final int DO_TRAVERSAL = 4;
7056        public static final int ADD_STARTING = 5;
7057        public static final int REMOVE_STARTING = 6;
7058        public static final int FINISHED_STARTING = 7;
7059        public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8;
7060        public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9;
7061        public static final int WINDOW_FREEZE_TIMEOUT = 11;
7062
7063        public static final int APP_TRANSITION_TIMEOUT = 13;
7064        public static final int PERSIST_ANIMATION_SCALE = 14;
7065        public static final int FORCE_GC = 15;
7066        public static final int ENABLE_SCREEN = 16;
7067        public static final int APP_FREEZE_TIMEOUT = 17;
7068        public static final int SEND_NEW_CONFIGURATION = 18;
7069        public static final int REPORT_WINDOWS_CHANGE = 19;
7070        public static final int DRAG_START_TIMEOUT = 20;
7071        public static final int DRAG_END_TIMEOUT = 21;
7072        public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22;
7073        public static final int BOOT_TIMEOUT = 23;
7074        public static final int WAITING_FOR_DRAWN_TIMEOUT = 24;
7075        public static final int SHOW_STRICT_MODE_VIOLATION = 25;
7076        public static final int DO_ANIMATION_CALLBACK = 26;
7077
7078        public static final int DO_DISPLAY_ADDED = 27;
7079        public static final int DO_DISPLAY_REMOVED = 28;
7080        public static final int DO_DISPLAY_CHANGED = 29;
7081
7082        public static final int CLIENT_FREEZE_TIMEOUT = 30;
7083        public static final int TAP_OUTSIDE_STACK = 31;
7084        public static final int NOTIFY_ACTIVITY_DRAWN = 32;
7085
7086        public static final int REMOVE_STARTING_TIMEOUT = 33;
7087
7088        @Override
7089        public void handleMessage(Message msg) {
7090            if (DEBUG_WINDOW_TRACE) {
7091                Slog.v(TAG, "handleMessage: entry what=" + msg.what);
7092            }
7093            switch (msg.what) {
7094                case REPORT_FOCUS_CHANGE: {
7095                    WindowState lastFocus;
7096                    WindowState newFocus;
7097
7098                    synchronized(mWindowMap) {
7099                        lastFocus = mLastFocus;
7100                        newFocus = mCurrentFocus;
7101                        if (lastFocus == newFocus) {
7102                            // Focus is not changing, so nothing to do.
7103                            return;
7104                        }
7105                        mLastFocus = newFocus;
7106                        if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Focus moving from " + lastFocus +
7107                                " to " + newFocus);
7108                        if (newFocus != null && lastFocus != null
7109                                && !newFocus.isDisplayedLw()) {
7110                            //Slog.i(TAG, "Delaying loss of focus...");
7111                            mLosingFocus.add(lastFocus);
7112                            lastFocus = null;
7113                        }
7114                    }
7115
7116                    //System.out.println("Changing focus from " + lastFocus
7117                    //                   + " to " + newFocus);
7118                    if (newFocus != null) {
7119                        if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Gaining focus: " + newFocus);
7120                        newFocus.reportFocusChangedSerialized(true, mInTouchMode);
7121                        notifyFocusChanged();
7122                    }
7123
7124                    if (lastFocus != null) {
7125                        if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing focus: " + lastFocus);
7126                        lastFocus.reportFocusChangedSerialized(false, mInTouchMode);
7127                    }
7128                } break;
7129
7130                case REPORT_LOSING_FOCUS: {
7131                    ArrayList<WindowState> losers;
7132
7133                    synchronized(mWindowMap) {
7134                        losers = mLosingFocus;
7135                        mLosingFocus = new ArrayList<WindowState>();
7136                    }
7137
7138                    final int N = losers.size();
7139                    for (int i=0; i<N; i++) {
7140                        if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing delayed focus: " +
7141                                losers.get(i));
7142                        losers.get(i).reportFocusChangedSerialized(false, mInTouchMode);
7143                    }
7144                } break;
7145
7146                case DO_TRAVERSAL: {
7147                    synchronized(mWindowMap) {
7148                        mTraversalScheduled = false;
7149                        performLayoutAndPlaceSurfacesLocked();
7150                    }
7151                } break;
7152
7153                case ADD_STARTING: {
7154                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7155                    final StartingData sd = wtoken.startingData;
7156
7157                    if (sd == null) {
7158                        // Animation has been canceled... do nothing.
7159                        return;
7160                    }
7161
7162                    if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting "
7163                            + wtoken + ": pkg=" + sd.pkg);
7164
7165                    View view = null;
7166                    try {
7167                        view = mPolicy.addStartingWindow(
7168                            wtoken.token, sd.pkg, sd.theme, sd.compatInfo,
7169                            sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo, sd.windowFlags);
7170                    } catch (Exception e) {
7171                        Slog.w(TAG, "Exception when adding starting window", e);
7172                    }
7173
7174                    if (view != null) {
7175                        boolean abort = false;
7176
7177                        synchronized(mWindowMap) {
7178                            if (wtoken.removed || wtoken.startingData == null) {
7179                                // If the window was successfully added, then
7180                                // we need to remove it.
7181                                if (wtoken.startingWindow != null) {
7182                                    if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
7183                                            "Aborted starting " + wtoken
7184                                            + ": removed=" + wtoken.removed
7185                                            + " startingData=" + wtoken.startingData);
7186                                    removeStartingWindowTimeout(wtoken);
7187                                    wtoken.startingWindow = null;
7188                                    wtoken.startingData = null;
7189                                    abort = true;
7190                                }
7191                            } else {
7192                                wtoken.startingView = view;
7193                            }
7194                            if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG,
7195                                    "Added starting " + wtoken
7196                                    + ": startingWindow="
7197                                    + wtoken.startingWindow + " startingView="
7198                                    + wtoken.startingView);
7199                        }
7200
7201                        if (abort) {
7202                            try {
7203                                mPolicy.removeStartingWindow(wtoken.token, view);
7204                            } catch (Exception e) {
7205                                Slog.w(TAG, "Exception when removing starting window", e);
7206                            }
7207                        }
7208                    }
7209                } break;
7210
7211                case REMOVE_STARTING_TIMEOUT: {
7212                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7213                    Slog.e(TAG, "Starting window " + wtoken + " timed out");
7214                    // Fall through.
7215                }
7216                case REMOVE_STARTING: {
7217                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7218                    IBinder token = null;
7219                    View view = null;
7220                    synchronized (mWindowMap) {
7221                        if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting "
7222                                + wtoken + ": startingWindow="
7223                                + wtoken.startingWindow + " startingView="
7224                                + wtoken.startingView);
7225                        if (wtoken.startingWindow != null) {
7226                            view = wtoken.startingView;
7227                            token = wtoken.token;
7228                            wtoken.startingData = null;
7229                            wtoken.startingView = null;
7230                            wtoken.startingWindow = null;
7231                            wtoken.startingDisplayed = false;
7232                        }
7233                    }
7234                    if (view != null) {
7235                        try {
7236                            mPolicy.removeStartingWindow(token, view);
7237                        } catch (Exception e) {
7238                            Slog.w(TAG, "Exception when removing starting window", e);
7239                        }
7240                    }
7241                } break;
7242
7243                case FINISHED_STARTING: {
7244                    IBinder token = null;
7245                    View view = null;
7246                    while (true) {
7247                        synchronized (mWindowMap) {
7248                            final int N = mFinishedStarting.size();
7249                            if (N <= 0) {
7250                                break;
7251                            }
7252                            AppWindowToken wtoken = mFinishedStarting.remove(N-1);
7253
7254                            if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
7255                                    "Finished starting " + wtoken
7256                                    + ": startingWindow=" + wtoken.startingWindow
7257                                    + " startingView=" + wtoken.startingView);
7258
7259                            if (wtoken.startingWindow == null) {
7260                                continue;
7261                            }
7262
7263                            view = wtoken.startingView;
7264                            token = wtoken.token;
7265                            wtoken.startingData = null;
7266                            wtoken.startingView = null;
7267                            wtoken.startingWindow = null;
7268                            wtoken.startingDisplayed = false;
7269                        }
7270
7271                        try {
7272                            mPolicy.removeStartingWindow(token, view);
7273                        } catch (Exception e) {
7274                            Slog.w(TAG, "Exception when removing starting window", e);
7275                        }
7276                    }
7277                } break;
7278
7279                case REPORT_APPLICATION_TOKEN_DRAWN: {
7280                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7281
7282                    try {
7283                        if (DEBUG_VISIBILITY) Slog.v(
7284                                TAG, "Reporting drawn in " + wtoken);
7285                        wtoken.appToken.windowsDrawn();
7286                    } catch (RemoteException ex) {
7287                    }
7288                } break;
7289
7290                case REPORT_APPLICATION_TOKEN_WINDOWS: {
7291                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7292
7293                    boolean nowVisible = msg.arg1 != 0;
7294                    boolean nowGone = msg.arg2 != 0;
7295
7296                    try {
7297                        if (DEBUG_VISIBILITY) Slog.v(
7298                                TAG, "Reporting visible in " + wtoken
7299                                + " visible=" + nowVisible
7300                                + " gone=" + nowGone);
7301                        if (nowVisible) {
7302                            wtoken.appToken.windowsVisible();
7303                        } else {
7304                            wtoken.appToken.windowsGone();
7305                        }
7306                    } catch (RemoteException ex) {
7307                    }
7308                } break;
7309
7310                case WINDOW_FREEZE_TIMEOUT: {
7311                    // TODO(multidisplay): Can non-default displays rotate?
7312                    synchronized (mWindowMap) {
7313                        Slog.w(TAG, "Window freeze timeout expired.");
7314                        final WindowList windows = getDefaultWindowListLocked();
7315                        int i = windows.size();
7316                        while (i > 0) {
7317                            i--;
7318                            WindowState w = windows.get(i);
7319                            if (w.mOrientationChanging) {
7320                                w.mOrientationChanging = false;
7321                                w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
7322                                        - mDisplayFreezeTime);
7323                                Slog.w(TAG, "Force clearing orientation change: " + w);
7324                            }
7325                        }
7326                        performLayoutAndPlaceSurfacesLocked();
7327                    }
7328                    break;
7329                }
7330
7331                case APP_TRANSITION_TIMEOUT: {
7332                    synchronized (mWindowMap) {
7333                        if (mAppTransition.isTransitionSet()) {
7334                            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** APP TRANSITION TIMEOUT");
7335                            mAppTransition.setTimeout();
7336                            performLayoutAndPlaceSurfacesLocked();
7337                        }
7338                    }
7339                    break;
7340                }
7341
7342                case PERSIST_ANIMATION_SCALE: {
7343                    Settings.Global.putFloat(mContext.getContentResolver(),
7344                            Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
7345                    Settings.Global.putFloat(mContext.getContentResolver(),
7346                            Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
7347                    Settings.Global.putFloat(mContext.getContentResolver(),
7348                            Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScale);
7349                    break;
7350                }
7351
7352                case FORCE_GC: {
7353                    synchronized (mWindowMap) {
7354                        // Since we're holding both mWindowMap and mAnimator we don't need to
7355                        // hold mAnimator.mLayoutToAnim.
7356                        if (mAnimator.mAnimating || mAnimationScheduled) {
7357                            // If we are animating, don't do the gc now but
7358                            // delay a bit so we don't interrupt the animation.
7359                            sendEmptyMessageDelayed(H.FORCE_GC, 2000);
7360                            return;
7361                        }
7362                        // If we are currently rotating the display, it will
7363                        // schedule a new message when done.
7364                        if (mDisplayFrozen) {
7365                            return;
7366                        }
7367                    }
7368                    Runtime.getRuntime().gc();
7369                    break;
7370                }
7371
7372                case ENABLE_SCREEN: {
7373                    performEnableScreen();
7374                    break;
7375                }
7376
7377                case APP_FREEZE_TIMEOUT: {
7378                    synchronized (mWindowMap) {
7379                        Slog.w(TAG, "App freeze timeout expired.");
7380                        DisplayContent displayContent = getDefaultDisplayContentLocked();
7381                        final ArrayList<Task> tasks = displayContent.getTasks();
7382                        for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
7383                            AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
7384                            for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
7385                                AppWindowToken tok = tokens.get(tokenNdx);
7386                                if (tok.mAppAnimator.freezingScreen) {
7387                                    Slog.w(TAG, "Force clearing freeze: " + tok);
7388                                    unsetAppFreezingScreenLocked(tok, true, true);
7389                                }
7390                            }
7391                        }
7392                    }
7393                    break;
7394                }
7395
7396                case CLIENT_FREEZE_TIMEOUT: {
7397                    synchronized (mWindowMap) {
7398                        if (mClientFreezingScreen) {
7399                            mClientFreezingScreen = false;
7400                            mLastFinishedFreezeSource = "client-timeout";
7401                            stopFreezingDisplayLocked();
7402                        }
7403                    }
7404                    break;
7405                }
7406
7407                case SEND_NEW_CONFIGURATION: {
7408                    removeMessages(SEND_NEW_CONFIGURATION);
7409                    sendNewConfiguration();
7410                    break;
7411                }
7412
7413                case REPORT_WINDOWS_CHANGE: {
7414                    if (mWindowsChanged) {
7415                        synchronized (mWindowMap) {
7416                            mWindowsChanged = false;
7417                        }
7418                        notifyWindowsChanged();
7419                    }
7420                    break;
7421                }
7422
7423                case DRAG_START_TIMEOUT: {
7424                    IBinder win = (IBinder)msg.obj;
7425                    if (DEBUG_DRAG) {
7426                        Slog.w(TAG, "Timeout starting drag by win " + win);
7427                    }
7428                    synchronized (mWindowMap) {
7429                        // !!! TODO: ANR the app that has failed to start the drag in time
7430                        if (mDragState != null) {
7431                            mDragState.unregister();
7432                            mInputMonitor.updateInputWindowsLw(true /*force*/);
7433                            mDragState.reset();
7434                            mDragState = null;
7435                        }
7436                    }
7437                    break;
7438                }
7439
7440                case DRAG_END_TIMEOUT: {
7441                    IBinder win = (IBinder)msg.obj;
7442                    if (DEBUG_DRAG) {
7443                        Slog.w(TAG, "Timeout ending drag to win " + win);
7444                    }
7445                    synchronized (mWindowMap) {
7446                        // !!! TODO: ANR the drag-receiving app
7447                        if (mDragState != null) {
7448                            mDragState.mDragResult = false;
7449                            mDragState.endDragLw();
7450                        }
7451                    }
7452                    break;
7453                }
7454
7455                case REPORT_HARD_KEYBOARD_STATUS_CHANGE: {
7456                    notifyHardKeyboardStatusChange();
7457                    break;
7458                }
7459
7460                case BOOT_TIMEOUT: {
7461                    performBootTimeout();
7462                    break;
7463                }
7464
7465                case WAITING_FOR_DRAWN_TIMEOUT: {
7466                    Pair<WindowState, IRemoteCallback> pair;
7467                    synchronized (mWindowMap) {
7468                        pair = (Pair<WindowState, IRemoteCallback>)msg.obj;
7469                        Slog.w(TAG, "Timeout waiting for drawn: " + pair.first);
7470                        if (!mWaitingForDrawn.remove(pair)) {
7471                            return;
7472                        }
7473                    }
7474                    try {
7475                        pair.second.sendResult(null);
7476                    } catch (RemoteException e) {
7477                    }
7478                    break;
7479                }
7480
7481                case SHOW_STRICT_MODE_VIOLATION: {
7482                    showStrictModeViolation(msg.arg1, msg.arg2);
7483                    break;
7484                }
7485
7486                case DO_ANIMATION_CALLBACK: {
7487                    try {
7488                        ((IRemoteCallback)msg.obj).sendResult(null);
7489                    } catch (RemoteException e) {
7490                    }
7491                    break;
7492                }
7493
7494                case DO_DISPLAY_ADDED:
7495                    synchronized (mWindowMap) {
7496                        handleDisplayAddedLocked(msg.arg1);
7497                    }
7498                    break;
7499
7500                case DO_DISPLAY_REMOVED:
7501                    synchronized (mWindowMap) {
7502                        handleDisplayRemovedLocked(msg.arg1);
7503                    }
7504                    break;
7505
7506                case DO_DISPLAY_CHANGED:
7507                    synchronized (mWindowMap) {
7508                        handleDisplayChangedLocked(msg.arg1);
7509                    }
7510                    break;
7511
7512                case TAP_OUTSIDE_STACK: {
7513                    int stackId;
7514                    synchronized (mWindowMap) {
7515                        stackId = ((DisplayContent)msg.obj).stackIdFromPoint(msg.arg1, msg.arg2);
7516                    }
7517                    if (stackId >= 0) {
7518                        try {
7519                            mActivityManager.setFocusedStack(stackId);
7520                        } catch (RemoteException e) {
7521                        }
7522                    }
7523                }
7524                break;
7525                case NOTIFY_ACTIVITY_DRAWN:
7526                    try {
7527                        mActivityManager.notifyActivityDrawn((IBinder) msg.obj);
7528                    } catch (RemoteException e) {
7529                    }
7530                    break;
7531            }
7532            if (DEBUG_WINDOW_TRACE) {
7533                Slog.v(TAG, "handleMessage: exit");
7534            }
7535        }
7536    }
7537
7538    // -------------------------------------------------------------
7539    // IWindowManager API
7540    // -------------------------------------------------------------
7541
7542    @Override
7543    public IWindowSession openSession(IInputMethodClient client,
7544            IInputContext inputContext) {
7545        if (client == null) throw new IllegalArgumentException("null client");
7546        if (inputContext == null) throw new IllegalArgumentException("null inputContext");
7547        Session session = new Session(this, client, inputContext);
7548        return session;
7549    }
7550
7551    @Override
7552    public boolean inputMethodClientHasFocus(IInputMethodClient client) {
7553        synchronized (mWindowMap) {
7554            // The focus for the client is the window immediately below
7555            // where we would place the input method window.
7556            int idx = findDesiredInputMethodWindowIndexLocked(false);
7557            if (idx > 0) {
7558                // TODO(multidisplay): IMEs are only supported on the default display.
7559                WindowState imFocus = getDefaultWindowListLocked().get(idx-1);
7560                if (DEBUG_INPUT_METHOD) {
7561                    Slog.i(TAG, "Desired input method target: " + imFocus);
7562                    Slog.i(TAG, "Current focus: " + mCurrentFocus);
7563                    Slog.i(TAG, "Last focus: " + mLastFocus);
7564                }
7565                if (imFocus != null) {
7566                    // This may be a starting window, in which case we still want
7567                    // to count it as okay.
7568                    if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING
7569                            && imFocus.mAppToken != null) {
7570                        // The client has definitely started, so it really should
7571                        // have a window in this app token.  Let's look for it.
7572                        for (int i=0; i<imFocus.mAppToken.windows.size(); i++) {
7573                            WindowState w = imFocus.mAppToken.windows.get(i);
7574                            if (w != imFocus) {
7575                                Log.i(TAG, "Switching to real app window: " + w);
7576                                imFocus = w;
7577                                break;
7578                            }
7579                        }
7580                    }
7581                    if (DEBUG_INPUT_METHOD) {
7582                        Slog.i(TAG, "IM target client: " + imFocus.mSession.mClient);
7583                        if (imFocus.mSession.mClient != null) {
7584                            Slog.i(TAG, "IM target client binder: "
7585                                    + imFocus.mSession.mClient.asBinder());
7586                            Slog.i(TAG, "Requesting client binder: " + client.asBinder());
7587                        }
7588                    }
7589                    if (imFocus.mSession.mClient != null &&
7590                            imFocus.mSession.mClient.asBinder() == client.asBinder()) {
7591                        return true;
7592                    }
7593                }
7594            }
7595
7596            // Okay, how about this...  what is the current focus?
7597            // It seems in some cases we may not have moved the IM
7598            // target window, such as when it was in a pop-up window,
7599            // so let's also look at the current focus.  (An example:
7600            // go to Gmail, start searching so the keyboard goes up,
7601            // press home.  Sometimes the IME won't go down.)
7602            // Would be nice to fix this more correctly, but it's
7603            // way at the end of a release, and this should be good enough.
7604            if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null
7605                    && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) {
7606                return true;
7607            }
7608        }
7609        return false;
7610    }
7611
7612    @Override
7613    public void getInitialDisplaySize(int displayId, Point size) {
7614        synchronized (mWindowMap) {
7615            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7616            if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
7617                synchronized(displayContent.mDisplaySizeLock) {
7618                    size.x = displayContent.mInitialDisplayWidth;
7619                    size.y = displayContent.mInitialDisplayHeight;
7620                }
7621            }
7622        }
7623    }
7624
7625    @Override
7626    public void getBaseDisplaySize(int displayId, Point size) {
7627        synchronized (mWindowMap) {
7628            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7629            if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
7630                synchronized(displayContent.mDisplaySizeLock) {
7631                    size.x = displayContent.mBaseDisplayWidth;
7632                    size.y = displayContent.mBaseDisplayHeight;
7633                }
7634            }
7635        }
7636    }
7637
7638    @Override
7639    public void setForcedDisplaySize(int displayId, int width, int height) {
7640        if (mContext.checkCallingOrSelfPermission(
7641                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7642                PackageManager.PERMISSION_GRANTED) {
7643            throw new SecurityException("Must hold permission " +
7644                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
7645        }
7646        if (displayId != Display.DEFAULT_DISPLAY) {
7647            throw new IllegalArgumentException("Can only set the default display");
7648        }
7649        synchronized(mWindowMap) {
7650            // Set some sort of reasonable bounds on the size of the display that we
7651            // will try to emulate.
7652            final int MIN_WIDTH = 200;
7653            final int MIN_HEIGHT = 200;
7654            final int MAX_SCALE = 2;
7655            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7656            if (displayContent != null) {
7657                width = Math.min(Math.max(width, MIN_WIDTH),
7658                        displayContent.mInitialDisplayWidth * MAX_SCALE);
7659                height = Math.min(Math.max(height, MIN_HEIGHT),
7660                        displayContent.mInitialDisplayHeight * MAX_SCALE);
7661                setForcedDisplaySizeLocked(displayContent, width, height);
7662                Settings.Global.putString(mContext.getContentResolver(),
7663                        Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height);
7664            }
7665        }
7666    }
7667
7668    private void readForcedDisplaySizeAndDensityLocked(final DisplayContent displayContent) {
7669        String sizeStr = Settings.Global.getString(mContext.getContentResolver(),
7670                Settings.Global.DISPLAY_SIZE_FORCED);
7671        if (sizeStr == null || sizeStr.length() == 0) {
7672            sizeStr = SystemProperties.get(SIZE_OVERRIDE, null);
7673        }
7674        if (sizeStr != null && sizeStr.length() > 0) {
7675            final int pos = sizeStr.indexOf(',');
7676            if (pos > 0 && sizeStr.lastIndexOf(',') == pos) {
7677                int width, height;
7678                try {
7679                    width = Integer.parseInt(sizeStr.substring(0, pos));
7680                    height = Integer.parseInt(sizeStr.substring(pos+1));
7681                    synchronized(displayContent.mDisplaySizeLock) {
7682                        if (displayContent.mBaseDisplayWidth != width
7683                                || displayContent.mBaseDisplayHeight != height) {
7684                            Slog.i(TAG, "FORCED DISPLAY SIZE: " + width + "x" + height);
7685                            displayContent.mBaseDisplayWidth = width;
7686                            displayContent.mBaseDisplayHeight = height;
7687                        }
7688                    }
7689                } catch (NumberFormatException ex) {
7690                }
7691            }
7692        }
7693        String densityStr = Settings.Global.getString(mContext.getContentResolver(),
7694                Settings.Global.DISPLAY_DENSITY_FORCED);
7695        if (densityStr == null || densityStr.length() == 0) {
7696            densityStr = SystemProperties.get(DENSITY_OVERRIDE, null);
7697        }
7698        if (densityStr != null && densityStr.length() > 0) {
7699            int density;
7700            try {
7701                density = Integer.parseInt(densityStr);
7702                synchronized(displayContent.mDisplaySizeLock) {
7703                    if (displayContent.mBaseDisplayDensity != density) {
7704                        Slog.i(TAG, "FORCED DISPLAY DENSITY: " + density);
7705                        displayContent.mBaseDisplayDensity = density;
7706                    }
7707                }
7708            } catch (NumberFormatException ex) {
7709            }
7710        }
7711    }
7712
7713    // displayContent must not be null
7714    private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {
7715        Slog.i(TAG, "Using new display size: " + width + "x" + height);
7716
7717        synchronized(displayContent.mDisplaySizeLock) {
7718            displayContent.mBaseDisplayWidth = width;
7719            displayContent.mBaseDisplayHeight = height;
7720        }
7721        reconfigureDisplayLocked(displayContent);
7722    }
7723
7724    @Override
7725    public void clearForcedDisplaySize(int displayId) {
7726        if (mContext.checkCallingOrSelfPermission(
7727                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7728                PackageManager.PERMISSION_GRANTED) {
7729            throw new SecurityException("Must hold permission " +
7730                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
7731        }
7732        if (displayId != Display.DEFAULT_DISPLAY) {
7733            throw new IllegalArgumentException("Can only set the default display");
7734        }
7735        synchronized(mWindowMap) {
7736            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7737            if (displayContent != null) {
7738                setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
7739                        displayContent.mInitialDisplayHeight);
7740                Settings.Global.putString(mContext.getContentResolver(),
7741                        Settings.Global.DISPLAY_SIZE_FORCED, "");
7742            }
7743        }
7744    }
7745
7746    @Override
7747    public int getInitialDisplayDensity(int displayId) {
7748        synchronized (mWindowMap) {
7749            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7750            if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
7751                synchronized(displayContent.mDisplaySizeLock) {
7752                    return displayContent.mInitialDisplayDensity;
7753                }
7754            }
7755        }
7756        return -1;
7757    }
7758
7759    @Override
7760    public int getBaseDisplayDensity(int displayId) {
7761        synchronized (mWindowMap) {
7762            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7763            if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
7764                synchronized(displayContent.mDisplaySizeLock) {
7765                    return displayContent.mBaseDisplayDensity;
7766                }
7767            }
7768        }
7769        return -1;
7770    }
7771
7772    @Override
7773    public void setForcedDisplayDensity(int displayId, int density) {
7774        if (mContext.checkCallingOrSelfPermission(
7775                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7776                PackageManager.PERMISSION_GRANTED) {
7777            throw new SecurityException("Must hold permission " +
7778                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
7779        }
7780        if (displayId != Display.DEFAULT_DISPLAY) {
7781            throw new IllegalArgumentException("Can only set the default display");
7782        }
7783        synchronized(mWindowMap) {
7784            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7785            if (displayContent != null) {
7786                setForcedDisplayDensityLocked(displayContent, density);
7787                Settings.Global.putString(mContext.getContentResolver(),
7788                        Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density));
7789            }
7790        }
7791    }
7792
7793    // displayContent must not be null
7794    private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) {
7795        Slog.i(TAG, "Using new display density: " + density);
7796
7797        synchronized(displayContent.mDisplaySizeLock) {
7798            displayContent.mBaseDisplayDensity = density;
7799        }
7800        reconfigureDisplayLocked(displayContent);
7801    }
7802
7803    @Override
7804    public void clearForcedDisplayDensity(int displayId) {
7805        if (mContext.checkCallingOrSelfPermission(
7806                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7807                PackageManager.PERMISSION_GRANTED) {
7808            throw new SecurityException("Must hold permission " +
7809                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
7810        }
7811        if (displayId != Display.DEFAULT_DISPLAY) {
7812            throw new IllegalArgumentException("Can only set the default display");
7813        }
7814        synchronized(mWindowMap) {
7815            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7816            if (displayContent != null) {
7817                setForcedDisplayDensityLocked(displayContent, displayContent.mInitialDisplayDensity);
7818                Settings.Global.putString(mContext.getContentResolver(),
7819                        Settings.Global.DISPLAY_DENSITY_FORCED, "");
7820            }
7821        }
7822    }
7823
7824    // displayContent must not be null
7825    private void reconfigureDisplayLocked(DisplayContent displayContent) {
7826        // TODO: Multidisplay: for now only use with default display.
7827        configureDisplayPolicyLocked(displayContent);
7828        displayContent.layoutNeeded = true;
7829
7830        boolean configChanged = updateOrientationFromAppTokensLocked(false);
7831        mTempConfiguration.setToDefaults();
7832        mTempConfiguration.fontScale = mCurConfiguration.fontScale;
7833        if (computeScreenConfigurationLocked(mTempConfiguration)) {
7834            if (mCurConfiguration.diff(mTempConfiguration) != 0) {
7835                configChanged = true;
7836            }
7837        }
7838
7839        if (configChanged) {
7840            mWaitingForConfig = true;
7841            startFreezingDisplayLocked(false, 0, 0);
7842            mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
7843        }
7844
7845        performLayoutAndPlaceSurfacesLocked();
7846    }
7847
7848    private void configureDisplayPolicyLocked(DisplayContent displayContent) {
7849        mPolicy.setInitialDisplaySize(displayContent.getDisplay(),
7850                displayContent.mBaseDisplayWidth,
7851                displayContent.mBaseDisplayHeight,
7852                displayContent.mBaseDisplayDensity);
7853
7854        DisplayInfo displayInfo = displayContent.getDisplayInfo();
7855        mPolicy.setDisplayOverscan(displayContent.getDisplay(),
7856                displayInfo.overscanLeft, displayInfo.overscanTop,
7857                displayInfo.overscanRight, displayInfo.overscanBottom);
7858    }
7859
7860    @Override
7861    public void setOverscan(int displayId, int left, int top, int right, int bottom) {
7862        if (mContext.checkCallingOrSelfPermission(
7863                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7864                PackageManager.PERMISSION_GRANTED) {
7865            throw new SecurityException("Must hold permission " +
7866                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
7867        }
7868        synchronized(mWindowMap) {
7869            DisplayContent displayContent = getDisplayContentLocked(displayId);
7870            if (displayContent != null) {
7871                setOverscanLocked(displayContent, left, top, right, bottom);
7872            }
7873        }
7874    }
7875
7876    private void setOverscanLocked(DisplayContent displayContent,
7877            int left, int top, int right, int bottom) {
7878        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
7879        synchronized (displayContent.mDisplaySizeLock) {
7880            displayInfo.overscanLeft = left;
7881            displayInfo.overscanTop = top;
7882            displayInfo.overscanRight = right;
7883            displayInfo.overscanBottom = bottom;
7884        }
7885
7886        mDisplaySettings.setOverscanLocked(displayInfo.name, left, top, right, bottom);
7887        mDisplaySettings.writeSettingsLocked();
7888
7889        reconfigureDisplayLocked(displayContent);
7890    }
7891
7892    // -------------------------------------------------------------
7893    // Internals
7894    // -------------------------------------------------------------
7895
7896    final WindowState windowForClientLocked(Session session, IWindow client,
7897            boolean throwOnError) {
7898        return windowForClientLocked(session, client.asBinder(), throwOnError);
7899    }
7900
7901    final WindowState windowForClientLocked(Session session, IBinder client,
7902            boolean throwOnError) {
7903        WindowState win = mWindowMap.get(client);
7904        if (localLOGV) Slog.v(
7905            TAG, "Looking up client " + client + ": " + win);
7906        if (win == null) {
7907            RuntimeException ex = new IllegalArgumentException(
7908                    "Requested window " + client + " does not exist");
7909            if (throwOnError) {
7910                throw ex;
7911            }
7912            Slog.w(TAG, "Failed looking up window", ex);
7913            return null;
7914        }
7915        if (session != null && win.mSession != session) {
7916            RuntimeException ex = new IllegalArgumentException(
7917                    "Requested window " + client + " is in session " +
7918                    win.mSession + ", not " + session);
7919            if (throwOnError) {
7920                throw ex;
7921            }
7922            Slog.w(TAG, "Failed looking up window", ex);
7923            return null;
7924        }
7925
7926        return win;
7927    }
7928
7929    final void rebuildAppWindowListLocked() {
7930        // TODO: Multidisplay, when ActivityStacks and tasks exist on more than one display.
7931        rebuildAppWindowListLocked(getDefaultDisplayContentLocked());
7932    }
7933
7934    private void rebuildAppWindowListLocked(final DisplayContent displayContent) {
7935        final WindowList windows = displayContent.getWindowList();
7936        int NW = windows.size();
7937        int i;
7938        int lastBelow = -1;
7939        int numRemoved = 0;
7940
7941        if (mRebuildTmp.length < NW) {
7942            mRebuildTmp = new WindowState[NW+10];
7943        }
7944
7945        // First remove all existing app windows.
7946        i=0;
7947        while (i < NW) {
7948            WindowState w = windows.get(i);
7949            if (w.mAppToken != null) {
7950                WindowState win = windows.remove(i);
7951                win.mRebuilding = true;
7952                mRebuildTmp[numRemoved] = win;
7953                mWindowsChanged = true;
7954                if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Rebuild removing window: " + win);
7955                NW--;
7956                numRemoved++;
7957                continue;
7958            } else if (lastBelow == i-1) {
7959                if (w.mAttrs.type == TYPE_WALLPAPER || w.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
7960                    lastBelow = i;
7961                }
7962            }
7963            i++;
7964        }
7965
7966        // Keep whatever windows were below the app windows still below,
7967        // by skipping them.
7968        lastBelow++;
7969        i = lastBelow;
7970
7971        // First add all of the exiting app tokens...  these are no longer
7972        // in the main app list, but still have windows shown.  We put them
7973        // in the back because now that the animation is over we no longer
7974        // will care about them.
7975        AppTokenList exitingAppTokens = displayContent.mExitingAppTokens;
7976        int NT = exitingAppTokens.size();
7977        for (int j=0; j<NT; j++) {
7978            i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j));
7979        }
7980
7981        // And add in the still active app tokens in Z order.
7982        final ArrayList<Task> tasks = displayContent.getTasks();
7983        final int numTasks = tasks.size();
7984        for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
7985            final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
7986            final int numTokens = tokens.size();
7987            for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
7988                final AppWindowToken wtoken = tokens.get(tokenNdx);
7989                i = reAddAppWindowsLocked(displayContent, i, wtoken);
7990            }
7991        }
7992
7993        i -= lastBelow;
7994        if (i != numRemoved) {
7995            Slog.w(TAG, "Rebuild removed " + numRemoved + " windows but added " + i,
7996                    new RuntimeException("here").fillInStackTrace());
7997            for (i=0; i<numRemoved; i++) {
7998                WindowState ws = mRebuildTmp[i];
7999                if (ws.mRebuilding) {
8000                    StringWriter sw = new StringWriter();
8001                    PrintWriter pw = new FastPrintWriter(sw, false, 1024);
8002                    ws.dump(pw, "", true);
8003                    pw.flush();
8004                    Slog.w(TAG, "This window was lost: " + ws);
8005                    Slog.w(TAG, sw.toString());
8006                    ws.mWinAnimator.destroySurfaceLocked();
8007                }
8008            }
8009            Slog.w(TAG, "Current app token list:");
8010            dumpAppTokensLocked();
8011            Slog.w(TAG, "Final window list:");
8012            dumpWindowsLocked();
8013        }
8014    }
8015
8016    private final void assignLayersLocked(WindowList windows) {
8017        int N = windows.size();
8018        int curBaseLayer = 0;
8019        int curLayer = 0;
8020        int i;
8021
8022        if (DEBUG_LAYERS) Slog.v(TAG, "Assigning layers based on windows=" + windows,
8023                new RuntimeException("here").fillInStackTrace());
8024
8025        boolean anyLayerChanged = false;
8026
8027        for (i=0; i<N; i++) {
8028            final WindowState w = windows.get(i);
8029            final WindowStateAnimator winAnimator = w.mWinAnimator;
8030            boolean layerChanged = false;
8031            int oldLayer = w.mLayer;
8032            if (w.mBaseLayer == curBaseLayer || w.mIsImWindow
8033                    || (i > 0 && w.mIsWallpaper)) {
8034                curLayer += WINDOW_LAYER_MULTIPLIER;
8035                w.mLayer = curLayer;
8036            } else {
8037                curBaseLayer = curLayer = w.mBaseLayer;
8038                w.mLayer = curLayer;
8039            }
8040            if (w.mLayer != oldLayer) {
8041                layerChanged = true;
8042                anyLayerChanged = true;
8043            }
8044            final AppWindowToken wtoken = w.mAppToken;
8045            oldLayer = winAnimator.mAnimLayer;
8046            if (w.mTargetAppToken != null) {
8047                winAnimator.mAnimLayer =
8048                        w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment;
8049            } else if (wtoken != null) {
8050                winAnimator.mAnimLayer =
8051                        w.mLayer + wtoken.mAppAnimator.animLayerAdjustment;
8052            } else {
8053                winAnimator.mAnimLayer = w.mLayer;
8054            }
8055            if (w.mIsImWindow) {
8056                winAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment;
8057            } else if (w.mIsWallpaper) {
8058                winAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment;
8059            }
8060            if (winAnimator.mAnimLayer != oldLayer) {
8061                layerChanged = true;
8062                anyLayerChanged = true;
8063            }
8064            if (layerChanged && w.getStack().isDimming(winAnimator)) {
8065                // Force an animation pass just to update the mDimLayer layer.
8066                scheduleAnimationLocked();
8067            }
8068            if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": "
8069                    + "mBase=" + w.mBaseLayer
8070                    + " mLayer=" + w.mLayer
8071                    + (wtoken == null ?
8072                            "" : " mAppLayer=" + wtoken.mAppAnimator.animLayerAdjustment)
8073                    + " =mAnimLayer=" + winAnimator.mAnimLayer);
8074            //System.out.println(
8075            //    "Assigned layer " + curLayer + " to " + w.mClient.asBinder());
8076        }
8077
8078        //TODO (multidisplay): Magnification is supported only for the default display.
8079        if (mDisplayMagnifier != null && anyLayerChanged
8080                && windows.get(windows.size() - 1).getDisplayId() == Display.DEFAULT_DISPLAY) {
8081            mDisplayMagnifier.onWindowLayersChangedLocked();
8082        }
8083    }
8084
8085    private final void performLayoutAndPlaceSurfacesLocked() {
8086        int loopCount = 6;
8087        do {
8088            mTraversalScheduled = false;
8089            performLayoutAndPlaceSurfacesLockedLoop();
8090            mH.removeMessages(H.DO_TRAVERSAL);
8091            loopCount--;
8092        } while (mTraversalScheduled && loopCount > 0);
8093        mInnerFields.mWallpaperActionPending = false;
8094    }
8095
8096    private boolean mInLayout = false;
8097    private final void performLayoutAndPlaceSurfacesLockedLoop() {
8098        if (mInLayout) {
8099            if (DEBUG) {
8100                throw new RuntimeException("Recursive call!");
8101            }
8102            Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers="
8103                    + Debug.getCallers(3));
8104            return;
8105        }
8106
8107        if (mWaitingForConfig) {
8108            // Our configuration has changed (most likely rotation), but we
8109            // don't yet have the complete configuration to report to
8110            // applications.  Don't do any window layout until we have it.
8111            return;
8112        }
8113
8114        if (!mDisplayReady) {
8115            // Not yet initialized, nothing to do.
8116            return;
8117        }
8118
8119        Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout");
8120        mInLayout = true;
8121        boolean recoveringMemory = false;
8122
8123        try {
8124            if (mForceRemoves != null) {
8125                recoveringMemory = true;
8126                // Wait a little bit for things to settle down, and off we go.
8127                for (int i=0; i<mForceRemoves.size(); i++) {
8128                    WindowState ws = mForceRemoves.get(i);
8129                    Slog.i(TAG, "Force removing: " + ws);
8130                    removeWindowInnerLocked(ws.mSession, ws);
8131                }
8132                mForceRemoves = null;
8133                Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");
8134                Object tmp = new Object();
8135                synchronized (tmp) {
8136                    try {
8137                        tmp.wait(250);
8138                    } catch (InterruptedException e) {
8139                    }
8140                }
8141            }
8142        } catch (RuntimeException e) {
8143            Log.wtf(TAG, "Unhandled exception while force removing for memory", e);
8144        }
8145
8146        try {
8147            performLayoutAndPlaceSurfacesLockedInner(recoveringMemory);
8148
8149            mInLayout = false;
8150
8151            if (needsLayout()) {
8152                if (++mLayoutRepeatCount < 6) {
8153                    requestTraversalLocked();
8154                } else {
8155                    Slog.e(TAG, "Performed 6 layouts in a row. Skipping");
8156                    mLayoutRepeatCount = 0;
8157                }
8158            } else {
8159                mLayoutRepeatCount = 0;
8160            }
8161
8162            if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) {
8163                mH.removeMessages(H.REPORT_WINDOWS_CHANGE);
8164                mH.sendEmptyMessage(H.REPORT_WINDOWS_CHANGE);
8165            }
8166        } catch (RuntimeException e) {
8167            mInLayout = false;
8168            Log.wtf(TAG, "Unhandled exception while laying out windows", e);
8169        }
8170
8171        Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
8172    }
8173
8174    private final void performLayoutLockedInner(final DisplayContent displayContent,
8175                                    boolean initial, boolean updateInputWindows) {
8176        if (!displayContent.layoutNeeded) {
8177            return;
8178        }
8179        displayContent.layoutNeeded = false;
8180        WindowList windows = displayContent.getWindowList();
8181        boolean isDefaultDisplay = displayContent.isDefaultDisplay;
8182
8183        DisplayInfo displayInfo = displayContent.getDisplayInfo();
8184        final int dw = displayInfo.logicalWidth;
8185        final int dh = displayInfo.logicalHeight;
8186
8187        final int NFW = mFakeWindows.size();
8188        for (int i=0; i<NFW; i++) {
8189            mFakeWindows.get(i).layout(dw, dh);
8190        }
8191
8192        final int N = windows.size();
8193        int i;
8194
8195        if (DEBUG_LAYOUT) {
8196            Slog.v(TAG, "-------------------------------------");
8197            Slog.v(TAG, "performLayout: needed="
8198                    + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh);
8199        }
8200
8201        WindowStateAnimator universeBackground = null;
8202
8203        mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mRotation);
8204        if (isDefaultDisplay) {
8205            // Not needed on non-default displays.
8206            mSystemDecorLayer = mPolicy.getSystemDecorLayerLw();
8207            mScreenRect.set(0, 0, dw, dh);
8208        }
8209
8210        mPolicy.getContentRectLw(mTmpContentRect);
8211        displayContent.setStackBoxSize(mTmpContentRect);
8212
8213        int seq = mLayoutSeq+1;
8214        if (seq < 0) seq = 0;
8215        mLayoutSeq = seq;
8216
8217        boolean behindDream = false;
8218
8219        // First perform layout of any root windows (not attached
8220        // to another window).
8221        int topAttached = -1;
8222        for (i = N-1; i >= 0; i--) {
8223            final WindowState win = windows.get(i);
8224
8225            // Don't do layout of a window if it is not visible, or
8226            // soon won't be visible, to avoid wasting time and funky
8227            // changes while a window is animating away.
8228            final boolean gone = (behindDream && mPolicy.canBeForceHidden(win, win.mAttrs))
8229                    || win.isGoneForLayoutLw();
8230
8231            if (DEBUG_LAYOUT && !win.mLayoutAttached) {
8232                Slog.v(TAG, "1ST PASS " + win
8233                        + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame
8234                        + " mLayoutAttached=" + win.mLayoutAttached
8235                        + " screen changed=" + win.isConfigChanged());
8236                final AppWindowToken atoken = win.mAppToken;
8237                if (gone) Slog.v(TAG, "  GONE: mViewVisibility="
8238                        + win.mViewVisibility + " mRelayoutCalled="
8239                        + win.mRelayoutCalled + " hidden="
8240                        + win.mRootToken.hidden + " hiddenRequested="
8241                        + (atoken != null && atoken.hiddenRequested)
8242                        + " mAttachedHidden=" + win.mAttachedHidden);
8243                else Slog.v(TAG, "  VIS: mViewVisibility="
8244                        + win.mViewVisibility + " mRelayoutCalled="
8245                        + win.mRelayoutCalled + " hidden="
8246                        + win.mRootToken.hidden + " hiddenRequested="
8247                        + (atoken != null && atoken.hiddenRequested)
8248                        + " mAttachedHidden=" + win.mAttachedHidden);
8249            }
8250
8251            // If this view is GONE, then skip it -- keep the current
8252            // frame, and let the caller know so they can ignore it
8253            // if they want.  (We do the normal layout for INVISIBLE
8254            // windows, since that means "perform layout as normal,
8255            // just don't display").
8256            if (!gone || !win.mHaveFrame || win.mLayoutNeeded
8257                    || (win.mAttrs.type == TYPE_KEYGUARD && win.isConfigChanged())
8258                    || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
8259                if (!win.mLayoutAttached) {
8260                    if (initial) {
8261                        //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
8262                        win.mContentChanged = false;
8263                    }
8264                    if (win.mAttrs.type == TYPE_DREAM) {
8265                        // Don't layout windows behind a dream, so that if it
8266                        // does stuff like hide the status bar we won't get a
8267                        // bad transition when it goes away.
8268                        behindDream = true;
8269                    }
8270                    win.mLayoutNeeded = false;
8271                    win.prelayout();
8272                    mPolicy.layoutWindowLw(win, win.mAttrs, null);
8273                    win.mLayoutSeq = seq;
8274                    if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame="
8275                            + win.mFrame + " mContainingFrame="
8276                            + win.mContainingFrame + " mDisplayFrame="
8277                            + win.mDisplayFrame);
8278                } else {
8279                    if (topAttached < 0) topAttached = i;
8280                }
8281            }
8282            if (win.mViewVisibility == View.VISIBLE
8283                    && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND
8284                    && universeBackground == null) {
8285                universeBackground = win.mWinAnimator;
8286            }
8287        }
8288
8289        if (mAnimator.mUniverseBackground  != universeBackground) {
8290            mFocusMayChange = true;
8291            mAnimator.mUniverseBackground = universeBackground;
8292        }
8293
8294        boolean attachedBehindDream = false;
8295
8296        // Now perform layout of attached windows, which usually
8297        // depend on the position of the window they are attached to.
8298        // XXX does not deal with windows that are attached to windows
8299        // that are themselves attached.
8300        for (i = topAttached; i >= 0; i--) {
8301            final WindowState win = windows.get(i);
8302
8303            if (win.mLayoutAttached) {
8304                if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win
8305                        + " mHaveFrame=" + win.mHaveFrame
8306                        + " mViewVisibility=" + win.mViewVisibility
8307                        + " mRelayoutCalled=" + win.mRelayoutCalled);
8308                // If this view is GONE, then skip it -- keep the current
8309                // frame, and let the caller know so they can ignore it
8310                // if they want.  (We do the normal layout for INVISIBLE
8311                // windows, since that means "perform layout as normal,
8312                // just don't display").
8313                if (attachedBehindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) {
8314                    continue;
8315                }
8316                if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled)
8317                        || !win.mHaveFrame || win.mLayoutNeeded) {
8318                    if (initial) {
8319                        //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
8320                        win.mContentChanged = false;
8321                    }
8322                    win.mLayoutNeeded = false;
8323                    win.prelayout();
8324                    mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow);
8325                    win.mLayoutSeq = seq;
8326                    if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame="
8327                            + win.mFrame + " mContainingFrame="
8328                            + win.mContainingFrame + " mDisplayFrame="
8329                            + win.mDisplayFrame);
8330                }
8331            } else if (win.mAttrs.type == TYPE_DREAM) {
8332                // Don't layout windows behind a dream, so that if it
8333                // does stuff like hide the status bar we won't get a
8334                // bad transition when it goes away.
8335                attachedBehindDream = behindDream;
8336            }
8337        }
8338
8339        // Window frames may have changed.  Tell the input dispatcher about it.
8340        mInputMonitor.setUpdateInputWindowsNeededLw();
8341        if (updateInputWindows) {
8342            mInputMonitor.updateInputWindowsLw(false /*force*/);
8343        }
8344
8345        mPolicy.finishLayoutLw();
8346    }
8347
8348    void makeWindowFreezingScreenIfNeededLocked(WindowState w) {
8349        // If the screen is currently frozen or off, then keep
8350        // it frozen/off until this window draws at its new
8351        // orientation.
8352        if (!okToDisplay()) {
8353            if (DEBUG_ORIENTATION) Slog.v(TAG,
8354                    "Changing surface while display frozen: " + w);
8355            w.mOrientationChanging = true;
8356            w.mLastFreezeDuration = 0;
8357            mInnerFields.mOrientationChangeComplete = false;
8358            if (!mWindowsFreezingScreen) {
8359                mWindowsFreezingScreen = true;
8360                // XXX should probably keep timeout from
8361                // when we first froze the display.
8362                mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
8363                mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT,
8364                        WINDOW_FREEZE_TIMEOUT_DURATION);
8365            }
8366        }
8367    }
8368
8369    /**
8370     * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
8371     * @param windows List of windows on default display.
8372     * @return bitmap indicating if another pass through layout must be made.
8373     */
8374    public int handleAppTransitionReadyLocked(WindowList windows) {
8375        int changes = 0;
8376        int i;
8377        int NN = mOpeningApps.size();
8378        boolean goodToGo = true;
8379        if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8380                "Checking " + NN + " opening apps (frozen="
8381                + mDisplayFrozen + " timeout="
8382                + mAppTransition.isTimeout() + ")...");
8383        if (!mDisplayFrozen && !mAppTransition.isTimeout()) {
8384            // If the display isn't frozen, wait to do anything until
8385            // all of the apps are ready.  Otherwise just go because
8386            // we'll unfreeze the display when everyone is ready.
8387            for (i=0; i<NN && goodToGo; i++) {
8388                AppWindowToken wtoken = mOpeningApps.get(i);
8389                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8390                        "Check opening app=" + wtoken + ": allDrawn="
8391                        + wtoken.allDrawn + " startingDisplayed="
8392                        + wtoken.startingDisplayed + " startingMoved="
8393                        + wtoken.startingMoved);
8394                if (!wtoken.allDrawn && !wtoken.startingDisplayed
8395                        && !wtoken.startingMoved) {
8396                    goodToGo = false;
8397                }
8398            }
8399        }
8400        if (goodToGo) {
8401            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO");
8402            int transit = mAppTransition.getAppTransition();
8403            if (mSkipAppTransitionAnimation) {
8404                transit = AppTransition.TRANSIT_UNSET;
8405            }
8406            mAppTransition.goodToGo();
8407            mStartingIconInTransition = false;
8408            mSkipAppTransitionAnimation = false;
8409
8410            mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
8411
8412            rebuildAppWindowListLocked();
8413
8414            // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper
8415            WindowState oldWallpaper =
8416                    mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating()
8417                        && !mWallpaperTarget.mWinAnimator.isDummyAnimation()
8418                    ? null : mWallpaperTarget;
8419
8420            mInnerFields.mWallpaperMayChange = false;
8421
8422            // The top-most window will supply the layout params,
8423            // and we will determine it below.
8424            LayoutParams animLp = null;
8425            int bestAnimLayer = -1;
8426            boolean fullscreenAnim = false;
8427
8428            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8429                    "New wallpaper target=" + mWallpaperTarget
8430                    + ", oldWallpaper=" + oldWallpaper
8431                    + ", lower target=" + mLowerWallpaperTarget
8432                    + ", upper target=" + mUpperWallpaperTarget);
8433
8434            boolean openingAppHasWallpaper = false;
8435            boolean closingAppHasWallpaper = false;
8436            final AppWindowToken lowerWallpaperAppToken;
8437            final AppWindowToken upperWallpaperAppToken;
8438            if (mLowerWallpaperTarget == null) {
8439                lowerWallpaperAppToken = upperWallpaperAppToken = null;
8440            } else {
8441                lowerWallpaperAppToken = mLowerWallpaperTarget.mAppToken;
8442                upperWallpaperAppToken = mUpperWallpaperTarget.mAppToken;
8443            }
8444
8445            // Do a first pass through the tokens for two
8446            // things:
8447            // (1) Determine if both the closing and opening
8448            // app token sets are wallpaper targets, in which
8449            // case special animations are needed
8450            // (since the wallpaper needs to stay static
8451            // behind them).
8452            // (2) Find the layout params of the top-most
8453            // application window in the tokens, which is
8454            // what will control the animation theme.
8455            final int NC = mClosingApps.size();
8456            NN = NC + mOpeningApps.size();
8457            for (i=0; i<NN; i++) {
8458                final AppWindowToken wtoken;
8459                if (i < NC) {
8460                    wtoken = mClosingApps.get(i);
8461                    if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
8462                        closingAppHasWallpaper = true;
8463                    }
8464                } else {
8465                    wtoken = mOpeningApps.get(i - NC);
8466                    if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
8467                        openingAppHasWallpaper = true;
8468                    }
8469                }
8470
8471                if (wtoken.appFullscreen) {
8472                    WindowState ws = wtoken.findMainWindow();
8473                    if (ws != null) {
8474                        animLp = ws.mAttrs;
8475                        bestAnimLayer = ws.mLayer;
8476                        fullscreenAnim = true;
8477                    }
8478                } else if (!fullscreenAnim) {
8479                    WindowState ws = wtoken.findMainWindow();
8480                    if (ws != null) {
8481                        if (ws.mLayer > bestAnimLayer) {
8482                            animLp = ws.mAttrs;
8483                            bestAnimLayer = ws.mLayer;
8484                        }
8485                    }
8486                }
8487            }
8488
8489            if (closingAppHasWallpaper && openingAppHasWallpaper) {
8490                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!");
8491                switch (transit) {
8492                    case AppTransition.TRANSIT_ACTIVITY_OPEN:
8493                    case AppTransition.TRANSIT_TASK_OPEN:
8494                    case AppTransition.TRANSIT_TASK_TO_FRONT:
8495                        transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN;
8496                        break;
8497                    case AppTransition.TRANSIT_ACTIVITY_CLOSE:
8498                    case AppTransition.TRANSIT_TASK_CLOSE:
8499                    case AppTransition.TRANSIT_TASK_TO_BACK:
8500                        transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE;
8501                        break;
8502                }
8503                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit: " + transit);
8504            } else if ((oldWallpaper != null) && !mOpeningApps.contains(oldWallpaper.mAppToken)) {
8505                // We are transitioning from an activity with
8506                // a wallpaper to one without.
8507                transit = AppTransition.TRANSIT_WALLPAPER_CLOSE;
8508                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8509                        "New transit away from wallpaper: " + transit);
8510            } else if (mWallpaperTarget != null && mWallpaperTarget.isVisibleLw()) {
8511                // We are transitioning from an activity without
8512                // a wallpaper to now showing the wallpaper
8513                transit = AppTransition.TRANSIT_WALLPAPER_OPEN;
8514                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8515                        "New transit into wallpaper: " + transit);
8516            }
8517
8518            // If all closing windows are obscured, then there is
8519            // no need to do an animation.  This is the case, for
8520            // example, when this transition is being done behind
8521            // the lock screen.
8522            if (!mPolicy.allowAppAnimationsLw()) {
8523                animLp = null;
8524            }
8525
8526            AppWindowToken topOpeningApp = null;
8527            int topOpeningLayer = 0;
8528
8529            NN = mOpeningApps.size();
8530            for (i=0; i<NN; i++) {
8531                AppWindowToken wtoken = mOpeningApps.get(i);
8532                final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
8533                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken);
8534                appAnimator.clearThumbnail();
8535                wtoken.inPendingTransaction = false;
8536                appAnimator.animation = null;
8537                setTokenVisibilityLocked(wtoken, animLp, true, transit, false);
8538                wtoken.updateReportedVisibilityLocked();
8539                wtoken.waitingToShow = false;
8540
8541                appAnimator.mAllAppWinAnimators.clear();
8542                final int N = wtoken.allAppWindows.size();
8543                for (int j = 0; j < N; j++) {
8544                    appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
8545                }
8546                mAnimator.mAnimating |= appAnimator.showAllWindowsLocked();
8547
8548                if (animLp != null) {
8549                    int layer = -1;
8550                    for (int j=0; j<wtoken.windows.size(); j++) {
8551                        WindowState win = wtoken.windows.get(j);
8552                        if (win.mWinAnimator.mAnimLayer > layer) {
8553                            layer = win.mWinAnimator.mAnimLayer;
8554                        }
8555                    }
8556                    if (topOpeningApp == null || layer > topOpeningLayer) {
8557                        topOpeningApp = wtoken;
8558                        topOpeningLayer = layer;
8559                    }
8560                }
8561            }
8562            NN = mClosingApps.size();
8563            for (i=0; i<NN; i++) {
8564                AppWindowToken wtoken = mClosingApps.get(i);
8565                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8566                        "Now closing app " + wtoken);
8567                wtoken.mAppAnimator.clearThumbnail();
8568                wtoken.inPendingTransaction = false;
8569                wtoken.mAppAnimator.animation = null;
8570                setTokenVisibilityLocked(wtoken, animLp, false,
8571                        transit, false);
8572                wtoken.updateReportedVisibilityLocked();
8573                wtoken.waitingToHide = false;
8574                // Force the allDrawn flag, because we want to start
8575                // this guy's animations regardless of whether it's
8576                // gotten drawn.
8577                wtoken.allDrawn = true;
8578                wtoken.deferClearAllDrawn = false;
8579            }
8580
8581            AppWindowAnimator appAnimator =
8582                    topOpeningApp == null ? null : topOpeningApp.mAppAnimator;
8583            Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail();
8584            if (nextAppTransitionThumbnail != null && appAnimator != null
8585                    && appAnimator.animation != null) {
8586                // This thumbnail animation is very special, we need to have
8587                // an extra surface with the thumbnail included with the animation.
8588                Rect dirty = new Rect(0, 0, nextAppTransitionThumbnail.getWidth(),
8589                        nextAppTransitionThumbnail.getHeight());
8590                try {
8591                    // TODO(multi-display): support other displays
8592                    final DisplayContent displayContent = getDefaultDisplayContentLocked();
8593                    final Display display = displayContent.getDisplay();
8594                    SurfaceControl surfaceControl = new SurfaceControl(mFxSession,
8595                            "thumbnail anim",
8596                            dirty.width(), dirty.height(),
8597                            PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
8598                    surfaceControl.setLayerStack(display.getLayerStack());
8599                    appAnimator.thumbnail = surfaceControl;
8600                    if (SHOW_TRANSACTIONS) Slog.i(TAG, "  THUMBNAIL " + surfaceControl + ": CREATE");
8601                    Surface drawSurface = new Surface();
8602                    drawSurface.copyFrom(surfaceControl);
8603                    Canvas c = drawSurface.lockCanvas(dirty);
8604                    c.drawBitmap(nextAppTransitionThumbnail, 0, 0, null);
8605                    drawSurface.unlockCanvasAndPost(c);
8606                    drawSurface.release();
8607                    appAnimator.thumbnailLayer = topOpeningLayer;
8608                    DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
8609                    Animation anim = mAppTransition.createThumbnailAnimationLocked(
8610                            transit, true, true, displayInfo.appWidth, displayInfo.appHeight);
8611                    appAnimator.thumbnailAnimation = anim;
8612                    anim.restrictDuration(MAX_ANIMATION_DURATION);
8613                    anim.scaleCurrentDuration(mTransitionAnimationScale);
8614                    Point p = new Point();
8615                    mAppTransition.getStartingPoint(p);
8616                    appAnimator.thumbnailX = p.x;
8617                    appAnimator.thumbnailY = p.y;
8618                } catch (OutOfResourcesException e) {
8619                    Slog.e(TAG, "Can't allocate thumbnail/Canvas surface w=" + dirty.width()
8620                            + " h=" + dirty.height(), e);
8621                    appAnimator.clearThumbnail();
8622                }
8623            }
8624
8625            mAppTransition.postAnimationCallback();
8626            mAppTransition.clear();
8627
8628            mOpeningApps.clear();
8629            mClosingApps.clear();
8630
8631            // This has changed the visibility of windows, so perform
8632            // a new layout to get them all up-to-date.
8633            changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT
8634                    | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
8635            getDefaultDisplayContentLocked().layoutNeeded = true;
8636
8637            // TODO(multidisplay): IMEs are only supported on the default display.
8638            if (windows == getDefaultWindowListLocked()
8639                    && !moveInputMethodWindowsIfNeededLocked(true)) {
8640                assignLayersLocked(windows);
8641            }
8642            updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, false /*updateInputWindows*/);
8643            mFocusMayChange = false;
8644        }
8645
8646        return changes;
8647    }
8648
8649    /**
8650     * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
8651     * @return bitmap indicating if another pass through layout must be made.
8652     */
8653    private int handleAnimatingStoppedAndTransitionLocked() {
8654        int changes = 0;
8655
8656        mAppTransition.setIdle();
8657        // Restore window app tokens to the ActivityManager views
8658        final DisplayContent displayContent = getDefaultDisplayContentLocked();
8659        final ArrayList<Task> tasks = displayContent.getTasks();
8660        final int numTasks = tasks.size();
8661        for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
8662            final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
8663            final int numTokens = tokens.size();
8664            for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
8665                final AppWindowToken wtoken = tokens.get(tokenNdx);
8666                wtoken.sendingToBottom = false;
8667            }
8668        }
8669        rebuildAppWindowListLocked();
8670
8671        changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
8672        if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
8673                "Wallpaper layer changed: assigning layers + relayout");
8674        moveInputMethodWindowsIfNeededLocked(true);
8675        mInnerFields.mWallpaperMayChange = true;
8676        // Since the window list has been rebuilt, focus might
8677        // have to be recomputed since the actual order of windows
8678        // might have changed again.
8679        mFocusMayChange = true;
8680
8681        return changes;
8682    }
8683
8684    private void updateResizingWindows(final WindowState w) {
8685        final WindowStateAnimator winAnimator = w.mWinAnimator;
8686        if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq) {
8687            w.mOverscanInsetsChanged |=
8688                    !w.mLastOverscanInsets.equals(w.mOverscanInsets);
8689            w.mContentInsetsChanged |=
8690                    !w.mLastContentInsets.equals(w.mContentInsets);
8691            w.mVisibleInsetsChanged |=
8692                    !w.mLastVisibleInsets.equals(w.mVisibleInsets);
8693            boolean configChanged = w.isConfigChanged();
8694            if (DEBUG_CONFIGURATION && configChanged) {
8695                Slog.v(TAG, "Win " + w + " config changed: "
8696                        + mCurConfiguration);
8697            }
8698            if (localLOGV) Slog.v(TAG, "Resizing " + w
8699                    + ": configChanged=" + configChanged
8700                    + " last=" + w.mLastFrame + " frame=" + w.mFrame);
8701            w.mLastFrame.set(w.mFrame);
8702            if (w.mContentInsetsChanged
8703                    || w.mVisibleInsetsChanged
8704                    || winAnimator.mSurfaceResized
8705                    || configChanged) {
8706                if (DEBUG_RESIZE || DEBUG_ORIENTATION) {
8707                    Slog.v(TAG, "Resize reasons for w=" + w + ": "
8708                            + " contentInsetsChanged=" + w.mContentInsetsChanged
8709                            + " " + w.mContentInsets.toShortString()
8710                            + " visibleInsetsChanged=" + w.mVisibleInsetsChanged
8711                            + " " + w.mVisibleInsets.toShortString()
8712                            + " surfaceResized=" + winAnimator.mSurfaceResized
8713                            + " configChanged=" + configChanged);
8714                }
8715
8716                w.mLastOverscanInsets.set(w.mOverscanInsets);
8717                w.mLastContentInsets.set(w.mContentInsets);
8718                w.mLastVisibleInsets.set(w.mVisibleInsets);
8719                makeWindowFreezingScreenIfNeededLocked(w);
8720                // If the orientation is changing, then we need to
8721                // hold off on unfreezing the display until this
8722                // window has been redrawn; to do that, we need
8723                // to go through the process of getting informed
8724                // by the application when it has finished drawing.
8725                if (w.mOrientationChanging) {
8726                    if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION) Slog.v(TAG,
8727                            "Orientation start waiting for draw mDrawState=DRAW_PENDING in "
8728                            + w + ", surface " + winAnimator.mSurfaceControl);
8729                    winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
8730                    if (w.mAppToken != null) {
8731                        w.mAppToken.allDrawn = false;
8732                        w.mAppToken.deferClearAllDrawn = false;
8733                    }
8734                }
8735                if (!mResizingWindows.contains(w)) {
8736                    if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
8737                            "Resizing window " + w + " to " + winAnimator.mSurfaceW
8738                            + "x" + winAnimator.mSurfaceH);
8739                    mResizingWindows.add(w);
8740                }
8741            } else if (w.mOrientationChanging) {
8742                if (w.isDrawnLw()) {
8743                    if (DEBUG_ORIENTATION) Slog.v(TAG,
8744                            "Orientation not waiting for draw in "
8745                            + w + ", surface " + winAnimator.mSurfaceControl);
8746                    w.mOrientationChanging = false;
8747                    w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
8748                            - mDisplayFreezeTime);
8749                }
8750            }
8751        }
8752    }
8753
8754    /**
8755     * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
8756     *
8757     * @param w WindowState this method is applied to.
8758     * @param currentTime The time which animations use for calculating transitions.
8759     * @param innerDw Width of app window.
8760     * @param innerDh Height of app window.
8761     */
8762    private void handleNotObscuredLocked(final WindowState w, final long currentTime,
8763                                         final int innerDw, final int innerDh) {
8764        final WindowManager.LayoutParams attrs = w.mAttrs;
8765        final int attrFlags = attrs.flags;
8766        final boolean canBeSeen = w.isDisplayedLw();
8767
8768        if (w.mHasSurface) {
8769            if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) {
8770                mInnerFields.mHoldScreen = w.mSession;
8771            }
8772            if (!mInnerFields.mSyswin && w.mAttrs.screenBrightness >= 0
8773                    && mInnerFields.mScreenBrightness < 0) {
8774                mInnerFields.mScreenBrightness = w.mAttrs.screenBrightness;
8775            }
8776            if (!mInnerFields.mSyswin && w.mAttrs.buttonBrightness >= 0
8777                    && mInnerFields.mButtonBrightness < 0) {
8778                mInnerFields.mButtonBrightness = w.mAttrs.buttonBrightness;
8779            }
8780            if (!mInnerFields.mSyswin && w.mAttrs.userActivityTimeout >= 0
8781                    && mInnerFields.mUserActivityTimeout < 0) {
8782                mInnerFields.mUserActivityTimeout = w.mAttrs.userActivityTimeout;
8783            }
8784
8785            final int type = attrs.type;
8786            if (canBeSeen
8787                    && (type == TYPE_SYSTEM_DIALOG
8788                     || type == TYPE_RECENTS_OVERLAY
8789                     || type == TYPE_KEYGUARD
8790                     || type == TYPE_SYSTEM_ERROR)) {
8791                mInnerFields.mSyswin = true;
8792            }
8793
8794            if (canBeSeen) {
8795                if (type == TYPE_DREAM || type == TYPE_KEYGUARD) {
8796                    mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_MIRROR;
8797                } else if (mInnerFields.mDisplayHasContent
8798                        == LayoutFields.DISPLAY_CONTENT_UNKNOWN) {
8799                    mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_UNIQUE;
8800                }
8801            }
8802        }
8803
8804        boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn();
8805        if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) {
8806            // This window completely covers everything behind it,
8807            // so we want to leave all of them as undimmed (for
8808            // performance reasons).
8809            mInnerFields.mObscured = true;
8810        }
8811    }
8812
8813    private void handleFlagDimBehind(WindowState w, int innerDw, int innerDh) {
8814        final WindowManager.LayoutParams attrs = w.mAttrs;
8815        if ((attrs.flags & FLAG_DIM_BEHIND) != 0
8816                && w.isDisplayedLw()
8817                && !w.mExiting) {
8818            final WindowStateAnimator winAnimator = w.mWinAnimator;
8819            final TaskStack stack = w.getStack();
8820            stack.setDimmingTag();
8821            if (!stack.isDimming(winAnimator)) {
8822                if (localLOGV) Slog.v(TAG, "Win " + w + " start dimming.");
8823                stack.startDimmingIfNeeded(winAnimator);
8824            }
8825        }
8826    }
8827
8828    private void updateAllDrawnLocked(DisplayContent displayContent) {
8829        // See if any windows have been drawn, so they (and others
8830        // associated with them) can now be shown.
8831        final ArrayList<Task> tasks = displayContent.getTasks();
8832        final int numTasks = tasks.size();
8833        for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
8834            final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
8835            final int numTokens = tokens.size();
8836            for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
8837                final AppWindowToken wtoken = tokens.get(tokenNdx);
8838                if (!wtoken.allDrawn) {
8839                    int numInteresting = wtoken.numInterestingWindows;
8840                    if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
8841                        if (DEBUG_VISIBILITY) Slog.v(TAG,
8842                                "allDrawn: " + wtoken
8843                                + " interesting=" + numInteresting
8844                                + " drawn=" + wtoken.numDrawnWindows);
8845                        wtoken.allDrawn = true;
8846                        mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, wtoken.token).sendToTarget();
8847                    }
8848                }
8849            }
8850        }
8851    }
8852
8853    // "Something has changed!  Let's make it correct now."
8854    private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) {
8855        if (DEBUG_WINDOW_TRACE) {
8856            Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by "
8857                    + Debug.getCallers(3));
8858        }
8859
8860        final long currentTime = SystemClock.uptimeMillis();
8861
8862        int i;
8863
8864        if (mFocusMayChange) {
8865            mFocusMayChange = false;
8866            updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
8867                    false /*updateInputWindows*/);
8868        }
8869
8870        // Initialize state of exiting tokens.
8871        final int numDisplays = mDisplayContents.size();
8872        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
8873            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
8874            for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) {
8875                displayContent.mExitingTokens.get(i).hasVisible = false;
8876            }
8877
8878            // Initialize state of exiting applications.
8879            for (i=displayContent.mExitingAppTokens.size()-1; i>=0; i--) {
8880                displayContent.mExitingAppTokens.get(i).hasVisible = false;
8881            }
8882        }
8883
8884        mInnerFields.mHoldScreen = null;
8885        mInnerFields.mScreenBrightness = -1;
8886        mInnerFields.mButtonBrightness = -1;
8887        mInnerFields.mUserActivityTimeout = -1;
8888        mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_UNKNOWN;
8889
8890        mTransactionSequence++;
8891
8892        final DisplayContent defaultDisplay = getDefaultDisplayContentLocked();
8893        final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo();
8894        final int defaultDw = defaultInfo.logicalWidth;
8895        final int defaultDh = defaultInfo.logicalHeight;
8896
8897        if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
8898                ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
8899        SurfaceControl.openTransaction();
8900        try {
8901
8902            if (mWatermark != null) {
8903                mWatermark.positionSurface(defaultDw, defaultDh);
8904            }
8905            if (mStrictModeFlash != null) {
8906                mStrictModeFlash.positionSurface(defaultDw, defaultDh);
8907            }
8908
8909            boolean focusDisplayed = false;
8910
8911            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
8912                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
8913                boolean updateAllDrawn = false;
8914                WindowList windows = displayContent.getWindowList();
8915                DisplayInfo displayInfo = displayContent.getDisplayInfo();
8916                final int displayId = displayContent.getDisplayId();
8917                final int dw = displayInfo.logicalWidth;
8918                final int dh = displayInfo.logicalHeight;
8919                final int innerDw = displayInfo.appWidth;
8920                final int innerDh = displayInfo.appHeight;
8921                final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
8922
8923                // Reset for each display unless we are forcing mirroring.
8924                if (mInnerFields.mDisplayHasContent != LayoutFields.DISPLAY_CONTENT_MIRROR) {
8925                    mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_UNKNOWN;
8926                }
8927
8928                int repeats = 0;
8929                do {
8930                    repeats++;
8931                    if (repeats > 6) {
8932                        Slog.w(TAG, "Animation repeat aborted after too many iterations");
8933                        displayContent.layoutNeeded = false;
8934                        break;
8935                    }
8936
8937                    if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner",
8938                        displayContent.pendingLayoutChanges);
8939
8940                    if ((displayContent.pendingLayoutChanges &
8941                            WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0 &&
8942                            (adjustWallpaperWindowsLocked() &
8943                                    ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
8944                        assignLayersLocked(windows);
8945                        displayContent.layoutNeeded = true;
8946                    }
8947
8948                    if (isDefaultDisplay && (displayContent.pendingLayoutChanges
8949                            & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
8950                        if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
8951                        if (updateOrientationFromAppTokensLocked(true)) {
8952                            displayContent.layoutNeeded = true;
8953                            mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
8954                        }
8955                    }
8956
8957                    if ((displayContent.pendingLayoutChanges
8958                            & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
8959                        displayContent.layoutNeeded = true;
8960                    }
8961
8962                    // FIRST LOOP: Perform a layout, if needed.
8963                    if (repeats < 4) {
8964                        performLayoutLockedInner(displayContent, repeats == 1,
8965                                false /*updateInputWindows*/);
8966                    } else {
8967                        Slog.w(TAG, "Layout repeat skipped after too many iterations");
8968                    }
8969
8970                    // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think
8971                    // it is animating.
8972                    displayContent.pendingLayoutChanges = 0;
8973
8974                    if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number "
8975                            + mLayoutRepeatCount, displayContent.pendingLayoutChanges);
8976
8977                    if (isDefaultDisplay) {
8978                        mPolicy.beginPostLayoutPolicyLw(dw, dh);
8979                        for (i = windows.size() - 1; i >= 0; i--) {
8980                            WindowState w = windows.get(i);
8981                            if (w.mHasSurface) {
8982                                mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs);
8983                            }
8984                        }
8985                        displayContent.pendingLayoutChanges |= mPolicy.finishPostLayoutPolicyLw();
8986                        if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats(
8987                            "after finishPostLayoutPolicyLw", displayContent.pendingLayoutChanges);
8988                    }
8989                } while (displayContent.pendingLayoutChanges != 0);
8990
8991                mInnerFields.mObscured = false;
8992                mInnerFields.mSyswin = false;
8993                displayContent.resetDimming();
8994
8995                // Only used if default window
8996                final boolean someoneLosingFocus = !mLosingFocus.isEmpty();
8997
8998                final int N = windows.size();
8999                for (i=N-1; i>=0; i--) {
9000                    WindowState w = windows.get(i);
9001
9002                    final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured;
9003
9004                    // Update effect.
9005                    w.mObscured = mInnerFields.mObscured;
9006                    if (!mInnerFields.mObscured) {
9007                        handleNotObscuredLocked(w, currentTime, innerDw, innerDh);
9008                    }
9009
9010                    if (!w.getStack().testDimmingTag()) {
9011                        handleFlagDimBehind(w, innerDw, innerDh);
9012                    }
9013
9014                    if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w)
9015                            && w.isVisibleLw()) {
9016                        // This is the wallpaper target and its obscured state
9017                        // changed... make sure the current wallaper's visibility
9018                        // has been updated accordingly.
9019                        updateWallpaperVisibilityLocked();
9020                    }
9021
9022                    final WindowStateAnimator winAnimator = w.mWinAnimator;
9023
9024                    // If the window has moved due to its containing
9025                    // content frame changing, then we'd like to animate
9026                    // it.
9027                    if (w.mHasSurface && w.shouldAnimateMove()) {
9028                        // Frame has moved, containing content frame
9029                        // has also moved, and we're not currently animating...
9030                        // let's do something.
9031                        Animation a = AnimationUtils.loadAnimation(mContext,
9032                                com.android.internal.R.anim.window_move_from_decor);
9033                        winAnimator.setAnimation(a);
9034                        winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left;
9035                        winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top;
9036                        try {
9037                            w.mClient.moved(w.mFrame.left, w.mFrame.top);
9038                        } catch (RemoteException e) {
9039                        }
9040                    }
9041
9042                    //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
9043                    w.mContentChanged = false;
9044
9045                    // Moved from updateWindowsAndWallpaperLocked().
9046                    if (w.mHasSurface) {
9047                        // Take care of the window being ready to display.
9048                        final boolean committed =
9049                                winAnimator.commitFinishDrawingLocked(currentTime);
9050                        if (isDefaultDisplay && committed) {
9051                            if (w.mAttrs.type == TYPE_DREAM) {
9052                                // HACK: When a dream is shown, it may at that
9053                                // point hide the lock screen.  So we need to
9054                                // redo the layout to let the phone window manager
9055                                // make this happen.
9056                                displayContent.pendingLayoutChanges |=
9057                                        WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9058                                if (DEBUG_LAYOUT_REPEATS) {
9059                                    debugLayoutRepeats(
9060                                        "dream and commitFinishDrawingLocked true",
9061                                        displayContent.pendingLayoutChanges);
9062                                }
9063                            }
9064                            if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
9065                                if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
9066                                        "First draw done in potential wallpaper target " + w);
9067                                mInnerFields.mWallpaperMayChange = true;
9068                                displayContent.pendingLayoutChanges |=
9069                                        WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
9070                                if (DEBUG_LAYOUT_REPEATS) {
9071                                    debugLayoutRepeats(
9072                                        "wallpaper and commitFinishDrawingLocked true",
9073                                        displayContent.pendingLayoutChanges);
9074                                }
9075                            }
9076                        }
9077
9078                        winAnimator.setSurfaceBoundariesLocked(recoveringMemory);
9079
9080                        final AppWindowToken atoken = w.mAppToken;
9081                        if (DEBUG_STARTING_WINDOW && atoken != null
9082                                && w == atoken.startingWindow) {
9083                            Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen="
9084                                + w.isOnScreen() + " allDrawn=" + atoken.allDrawn
9085                                + " freezingScreen=" + atoken.mAppAnimator.freezingScreen);
9086                        }
9087                        if (atoken != null
9088                                && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) {
9089                            if (atoken.lastTransactionSequence != mTransactionSequence) {
9090                                atoken.lastTransactionSequence = mTransactionSequence;
9091                                atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
9092                                atoken.startingDisplayed = false;
9093                            }
9094                            if ((w.isOnScreen() || winAnimator.mAttrType == TYPE_BASE_APPLICATION)
9095                                    && !w.mExiting && !w.mDestroying) {
9096                                if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
9097                                    Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
9098                                            + ", isAnimating=" + winAnimator.isAnimating());
9099                                    if (!w.isDrawnLw()) {
9100                                        Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceControl
9101                                                + " pv=" + w.mPolicyVisibility
9102                                                + " mDrawState=" + winAnimator.mDrawState
9103                                                + " ah=" + w.mAttachedHidden
9104                                                + " th=" + atoken.hiddenRequested
9105                                                + " a=" + winAnimator.mAnimating);
9106                                    }
9107                                }
9108                                if (w != atoken.startingWindow) {
9109                                    if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) {
9110                                        atoken.numInterestingWindows++;
9111                                        if (w.isDrawnLw()) {
9112                                            atoken.numDrawnWindows++;
9113                                            if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG,
9114                                                    "tokenMayBeDrawn: " + atoken
9115                                                    + " freezingScreen=" + atoken.mAppAnimator.freezingScreen
9116                                                    + " mAppFreezing=" + w.mAppFreezing);
9117                                            updateAllDrawn = true;
9118                                        }
9119                                    }
9120                                } else if (w.isDrawnLw()) {
9121                                    atoken.startingDisplayed = true;
9122                                }
9123                            }
9124                        }
9125                    }
9126
9127                    if (isDefaultDisplay && someoneLosingFocus && (w == mCurrentFocus)
9128                            && w.isDisplayedLw()) {
9129                        focusDisplayed = true;
9130                    }
9131
9132                    updateResizingWindows(w);
9133                }
9134
9135                final boolean hasUniqueContent;
9136                switch (mInnerFields.mDisplayHasContent) {
9137                    case LayoutFields.DISPLAY_CONTENT_MIRROR:
9138                        hasUniqueContent = isDefaultDisplay;
9139                        break;
9140                    case LayoutFields.DISPLAY_CONTENT_UNIQUE:
9141                        hasUniqueContent = true;
9142                        break;
9143                    case LayoutFields.DISPLAY_CONTENT_UNKNOWN:
9144                    default:
9145                        hasUniqueContent = false;
9146                        break;
9147                }
9148                mDisplayManagerService.setDisplayHasContent(displayId, hasUniqueContent,
9149                        true /* inTraversal, must call performTraversalInTrans... below */);
9150
9151                getDisplayContentLocked(displayId).stopDimmingIfNeeded();
9152
9153                if (updateAllDrawn) {
9154                    updateAllDrawnLocked(displayContent);
9155                }
9156            }
9157
9158            if (focusDisplayed) {
9159                mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS);
9160            }
9161
9162            // Give the display manager a chance to adjust properties
9163            // like display rotation if it needs to.
9164            mDisplayManagerService.performTraversalInTransactionFromWindowManager();
9165
9166        } catch (RuntimeException e) {
9167            Log.wtf(TAG, "Unhandled exception in Window Manager", e);
9168        } finally {
9169            SurfaceControl.closeTransaction();
9170            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
9171                    "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
9172        }
9173
9174        final WindowList defaultWindows = defaultDisplay.getWindowList();
9175
9176        // If we are ready to perform an app transition, check through
9177        // all of the app tokens to be shown and see if they are ready
9178        // to go.
9179        if (mAppTransition.isReady()) {
9180            defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows);
9181            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked",
9182                    defaultDisplay.pendingLayoutChanges);
9183        }
9184
9185        if (!mAnimator.mAnimating && mAppTransition.isRunning()) {
9186            // We have finished the animation of an app transition.  To do
9187            // this, we have delayed a lot of operations like showing and
9188            // hiding apps, moving apps in Z-order, etc.  The app token list
9189            // reflects the correct Z-order, but the window list may now
9190            // be out of sync with it.  So here we will just rebuild the
9191            // entire app window list.  Fun!
9192            defaultDisplay.pendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked();
9193            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock",
9194                defaultDisplay.pendingLayoutChanges);
9195        }
9196
9197        if (mInnerFields.mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0
9198                && !mAppTransition.isReady()) {
9199            // At this point, there was a window with a wallpaper that
9200            // was force hiding other windows behind it, but now it
9201            // is going away.  This may be simple -- just animate
9202            // away the wallpaper and its window -- or it may be
9203            // hard -- the wallpaper now needs to be shown behind
9204            // something that was hidden.
9205            defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9206            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked",
9207                defaultDisplay.pendingLayoutChanges);
9208        }
9209        mInnerFields.mWallpaperForceHidingChanged = false;
9210
9211        if (mInnerFields.mWallpaperMayChange) {
9212            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Wallpaper may change!  Adjusting");
9213            defaultDisplay.pendingLayoutChanges |=
9214                    WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
9215            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("WallpaperMayChange",
9216                    defaultDisplay.pendingLayoutChanges);
9217        }
9218
9219        if (mFocusMayChange) {
9220            mFocusMayChange = false;
9221            if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
9222                    false /*updateInputWindows*/)) {
9223                defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
9224            }
9225        }
9226
9227        if (needsLayout()) {
9228            defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9229            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded",
9230                    defaultDisplay.pendingLayoutChanges);
9231        }
9232
9233        for (i = mResizingWindows.size() - 1; i >= 0; i--) {
9234            WindowState win = mResizingWindows.get(i);
9235            if (win.mAppFreezing) {
9236                // Don't remove this window until rotation has completed.
9237                continue;
9238            }
9239            final WindowStateAnimator winAnimator = win.mWinAnimator;
9240            try {
9241                if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
9242                        "Reporting new frame to " + win + ": " + win.mCompatFrame);
9243                int diff = 0;
9244                boolean configChanged = win.isConfigChanged();
9245                if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION)
9246                        && configChanged) {
9247                    Slog.i(TAG, "Sending new config to window " + win + ": "
9248                            + winAnimator.mSurfaceW + "x" + winAnimator.mSurfaceH
9249                            + " / " + mCurConfiguration + " / 0x"
9250                            + Integer.toHexString(diff));
9251                }
9252                win.setConfiguration(mCurConfiguration);
9253                if (DEBUG_ORIENTATION &&
9254                        winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING) Slog.i(
9255                        TAG, "Resizing " + win + " WITH DRAW PENDING");
9256                final IWindow client = win.mClient;
9257                final Rect frame = win.mFrame;
9258                final Rect overscanInsets = win.mLastOverscanInsets;
9259                final Rect contentInsets = win.mLastContentInsets;
9260                final Rect visibleInsets = win.mLastVisibleInsets;
9261                final boolean reportDraw
9262                        = winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING;
9263                final Configuration newConfig = configChanged ? win.mConfiguration : null;
9264                if (win.mClient instanceof IWindow.Stub) {
9265                    // To prevent deadlock simulate one-way call if win.mClient is a local object.
9266                    mH.post(new Runnable() {
9267                        @Override
9268                        public void run() {
9269                            try {
9270                                client.resized(frame, overscanInsets, contentInsets,
9271                                        visibleInsets, reportDraw, newConfig);
9272                            } catch (RemoteException e) {
9273                                // Not a remote call, RemoteException won't be raised.
9274                            }
9275                        }
9276                    });
9277                } else {
9278                   client.resized(frame, overscanInsets, contentInsets, visibleInsets, reportDraw,
9279                           newConfig);
9280                }
9281                win.mOverscanInsetsChanged = false;
9282                win.mContentInsetsChanged = false;
9283                win.mVisibleInsetsChanged = false;
9284                winAnimator.mSurfaceResized = false;
9285            } catch (RemoteException e) {
9286                win.mOrientationChanging = false;
9287                win.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
9288                        - mDisplayFreezeTime);
9289            }
9290            mResizingWindows.remove(i);
9291        }
9292
9293        if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG,
9294                "With display frozen, orientationChangeComplete="
9295                + mInnerFields.mOrientationChangeComplete);
9296        if (mInnerFields.mOrientationChangeComplete) {
9297            if (mWindowsFreezingScreen) {
9298                mWindowsFreezingScreen = false;
9299                mLastFinishedFreezeSource = mInnerFields.mLastWindowFreezeSource;
9300                mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
9301            }
9302            stopFreezingDisplayLocked();
9303        }
9304
9305        // Destroy the surface of any windows that are no longer visible.
9306        boolean wallpaperDestroyed = false;
9307        i = mDestroySurface.size();
9308        if (i > 0) {
9309            do {
9310                i--;
9311                WindowState win = mDestroySurface.get(i);
9312                win.mDestroying = false;
9313                if (mInputMethodWindow == win) {
9314                    mInputMethodWindow = null;
9315                }
9316                if (win == mWallpaperTarget) {
9317                    wallpaperDestroyed = true;
9318                }
9319                win.mWinAnimator.destroySurfaceLocked();
9320            } while (i > 0);
9321            mDestroySurface.clear();
9322        }
9323
9324        // Time to remove any exiting tokens?
9325        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9326            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9327            ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens;
9328            for (i = exitingTokens.size() - 1; i >= 0; i--) {
9329                WindowToken token = exitingTokens.get(i);
9330                if (!token.hasVisible) {
9331                    exitingTokens.remove(i);
9332                    if (token.windowType == TYPE_WALLPAPER) {
9333                        mWallpaperTokens.remove(token);
9334                    }
9335                }
9336            }
9337
9338            // Time to remove any exiting applications?
9339            AppTokenList exitingAppTokens = displayContent.mExitingAppTokens;
9340            for (i = exitingAppTokens.size() - 1; i >= 0; i--) {
9341                AppWindowToken token = exitingAppTokens.get(i);
9342                if (!token.hasVisible && !mClosingApps.contains(token)) {
9343                    // Make sure there is no animation running on this token,
9344                    // so any windows associated with it will be removed as
9345                    // soon as their animations are complete
9346                    token.mAppAnimator.clearAnimation();
9347                    token.mAppAnimator.animating = false;
9348                    if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
9349                            "performLayout: App token exiting now removed" + token);
9350                    final Task task = mTaskIdToTask.get(token.groupId);
9351                    if (task != null && task.removeAppToken(token)) {
9352                        mTaskIdToTask.delete(token.groupId);
9353                    }
9354                    exitingAppTokens.remove(i);
9355                }
9356            }
9357        }
9358
9359        if (!mAnimator.mAnimating && mRelayoutWhileAnimating.size() > 0) {
9360            for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) {
9361                try {
9362                    mRelayoutWhileAnimating.get(j).mClient.doneAnimating();
9363                } catch (RemoteException e) {
9364                }
9365            }
9366            mRelayoutWhileAnimating.clear();
9367        }
9368
9369        if (wallpaperDestroyed) {
9370            defaultDisplay.pendingLayoutChanges |=
9371                    WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
9372            defaultDisplay.layoutNeeded = true;
9373        }
9374
9375        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9376            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9377            if (displayContent.pendingLayoutChanges != 0) {
9378                displayContent.layoutNeeded = true;
9379            }
9380        }
9381
9382        // Finally update all input windows now that the window changes have stabilized.
9383        mInputMonitor.updateInputWindowsLw(true /*force*/);
9384
9385        setHoldScreenLocked(mInnerFields.mHoldScreen);
9386        if (!mDisplayFrozen) {
9387            if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) {
9388                mPowerManager.setScreenBrightnessOverrideFromWindowManager(-1);
9389            } else {
9390                mPowerManager.setScreenBrightnessOverrideFromWindowManager(
9391                        toBrightnessOverride(mInnerFields.mScreenBrightness));
9392            }
9393            if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) {
9394                mPowerManager.setButtonBrightnessOverrideFromWindowManager(-1);
9395            } else {
9396                mPowerManager.setButtonBrightnessOverrideFromWindowManager(
9397                        toBrightnessOverride(mInnerFields.mButtonBrightness));
9398            }
9399            mPowerManager.setUserActivityTimeoutOverrideFromWindowManager(
9400                    mInnerFields.mUserActivityTimeout);
9401        }
9402
9403        if (mTurnOnScreen) {
9404            if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!");
9405            mPowerManager.wakeUp(SystemClock.uptimeMillis());
9406            mTurnOnScreen = false;
9407        }
9408
9409        if (mInnerFields.mUpdateRotation) {
9410            if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
9411            if (updateRotationUncheckedLocked(false)) {
9412                mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
9413            } else {
9414                mInnerFields.mUpdateRotation = false;
9415            }
9416        }
9417
9418        if (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded
9419                && !mInnerFields.mUpdateRotation) {
9420            checkDrawnWindowsLocked();
9421        }
9422
9423        final int N = mPendingRemove.size();
9424        if (N > 0) {
9425            if (mPendingRemoveTmp.length < N) {
9426                mPendingRemoveTmp = new WindowState[N+10];
9427            }
9428            mPendingRemove.toArray(mPendingRemoveTmp);
9429            mPendingRemove.clear();
9430            DisplayContentList displayList = new DisplayContentList();
9431            for (i = 0; i < N; i++) {
9432                WindowState w = mPendingRemoveTmp[i];
9433                removeWindowInnerLocked(w.mSession, w);
9434                if (!displayList.contains(w.mDisplayContent)) {
9435                    displayList.add(w.mDisplayContent);
9436                }
9437            }
9438
9439            for (DisplayContent displayContent : displayList) {
9440                assignLayersLocked(displayContent.getWindowList());
9441                displayContent.layoutNeeded = true;
9442            }
9443        }
9444
9445        setFocusedStackFrame();
9446
9447        // Check to see if we are now in a state where the screen should
9448        // be enabled, because the window obscured flags have changed.
9449        enableScreenIfNeededLocked();
9450
9451        scheduleAnimationLocked();
9452
9453        if (DEBUG_WINDOW_TRACE) {
9454            Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: animating="
9455                    + mAnimator.mAnimating);
9456        }
9457    }
9458
9459    private int toBrightnessOverride(float value) {
9460        return (int)(value * PowerManager.BRIGHTNESS_ON);
9461    }
9462
9463    void checkDrawnWindowsLocked() {
9464        if (mWaitingForDrawn.size() > 0) {
9465            for (int j=mWaitingForDrawn.size()-1; j>=0; j--) {
9466                Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(j);
9467                WindowState win = pair.first;
9468                //Slog.i(TAG, "Waiting for drawn " + win + ": removed="
9469                //        + win.mRemoved + " visible=" + win.isVisibleLw()
9470                //        + " shown=" + win.mSurfaceShown);
9471                if (win.mRemoved) {
9472                    // Window has been removed; no draw will now happen, so stop waiting.
9473                    Slog.w(TAG, "Aborted waiting for drawn: " + pair.first);
9474                    try {
9475                        pair.second.sendResult(null);
9476                    } catch (RemoteException e) {
9477                    }
9478                    mWaitingForDrawn.remove(pair);
9479                    mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
9480                } else if (win.mWinAnimator.mSurfaceShown) {
9481                    // Window is now drawn (and shown).
9482                    try {
9483                        pair.second.sendResult(null);
9484                    } catch (RemoteException e) {
9485                    }
9486                    mWaitingForDrawn.remove(pair);
9487                    mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
9488                }
9489            }
9490        }
9491    }
9492
9493    @Override
9494    public boolean waitForWindowDrawn(IBinder token, IRemoteCallback callback) {
9495        if (token != null && callback != null) {
9496            synchronized (mWindowMap) {
9497                WindowState win = windowForClientLocked(null, token, true);
9498                if (win != null) {
9499                    Pair<WindowState, IRemoteCallback> pair =
9500                            new Pair<WindowState, IRemoteCallback>(win, callback);
9501                    Message m = mH.obtainMessage(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
9502                    mH.sendMessageDelayed(m, 2000);
9503                    mWaitingForDrawn.add(pair);
9504                    checkDrawnWindowsLocked();
9505                    return true;
9506                }
9507                Slog.i(TAG, "waitForWindowDrawn: win null");
9508            }
9509        }
9510        return false;
9511    }
9512
9513    void setHoldScreenLocked(final Session newHoldScreen) {
9514        final boolean hold = newHoldScreen != null;
9515
9516        if (hold && mHoldingScreenOn != newHoldScreen) {
9517            mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid));
9518        }
9519        mHoldingScreenOn = newHoldScreen;
9520
9521        final boolean state = mHoldingScreenWakeLock.isHeld();
9522        if (hold != state) {
9523            if (hold) {
9524                mHoldingScreenWakeLock.acquire();
9525                mPolicy.keepScreenOnStartedLw();
9526            } else {
9527                mPolicy.keepScreenOnStoppedLw();
9528                mHoldingScreenWakeLock.release();
9529            }
9530        }
9531    }
9532
9533    @Override
9534    public void requestTraversal() {
9535        synchronized (mWindowMap) {
9536            requestTraversalLocked();
9537        }
9538    }
9539
9540    void requestTraversalLocked() {
9541        if (!mTraversalScheduled) {
9542            mTraversalScheduled = true;
9543            mH.sendEmptyMessage(H.DO_TRAVERSAL);
9544        }
9545    }
9546
9547    /** Note that Locked in this case is on mLayoutToAnim */
9548    void scheduleAnimationLocked() {
9549        if (!mAnimationScheduled) {
9550            mAnimationScheduled = true;
9551            mChoreographer.postCallback(
9552                    Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null);
9553        }
9554    }
9555
9556    private boolean needsLayout() {
9557        final int numDisplays = mDisplayContents.size();
9558        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9559            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9560            if (displayContent.layoutNeeded) {
9561                return true;
9562            }
9563        }
9564        return false;
9565    }
9566
9567    boolean copyAnimToLayoutParamsLocked() {
9568        boolean doRequest = false;
9569
9570        final int bulkUpdateParams = mAnimator.mBulkUpdateParams;
9571        if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) {
9572            mInnerFields.mUpdateRotation = true;
9573            doRequest = true;
9574        }
9575        if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) {
9576            mInnerFields.mWallpaperMayChange = true;
9577            doRequest = true;
9578        }
9579        if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) {
9580            mInnerFields.mWallpaperForceHidingChanged = true;
9581            doRequest = true;
9582        }
9583        if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) == 0) {
9584            mInnerFields.mOrientationChangeComplete = false;
9585        } else {
9586            mInnerFields.mOrientationChangeComplete = true;
9587            mInnerFields.mLastWindowFreezeSource = mAnimator.mLastWindowFreezeSource;
9588            if (mWindowsFreezingScreen) {
9589                doRequest = true;
9590            }
9591        }
9592        if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) {
9593            mTurnOnScreen = true;
9594        }
9595        if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_ACTION_PENDING) != 0) {
9596            mInnerFields.mWallpaperActionPending = true;
9597        }
9598
9599        return doRequest;
9600    }
9601
9602    /** If a window that has an animation specifying a colored background and the current wallpaper
9603     * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to
9604     * suddenly disappear. */
9605    int adjustAnimationBackground(WindowStateAnimator winAnimator) {
9606        WindowList windows = winAnimator.mWin.getWindowList();
9607        for (int i = windows.size() - 1; i >= 0; --i) {
9608            WindowState testWin = windows.get(i);
9609            if (testWin.mIsWallpaper && testWin.isVisibleNow()) {
9610                return testWin.mWinAnimator.mAnimLayer;
9611            }
9612        }
9613        return winAnimator.mAnimLayer;
9614    }
9615
9616    boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation,
9617                                           boolean secure) {
9618        final SurfaceControl surface = winAnimator.mSurfaceControl;
9619        boolean leakedSurface = false;
9620        boolean killedApps = false;
9621
9622        EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(),
9623                winAnimator.mSession.mPid, operation);
9624
9625        if (mForceRemoves == null) {
9626            mForceRemoves = new ArrayList<WindowState>();
9627        }
9628
9629        long callingIdentity = Binder.clearCallingIdentity();
9630        try {
9631            // There was some problem...   first, do a sanity check of the
9632            // window list to make sure we haven't left any dangling surfaces
9633            // around.
9634
9635            Slog.i(TAG, "Out of memory for surface!  Looking for leaks...");
9636            final int numDisplays = mDisplayContents.size();
9637            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9638                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
9639                final int numWindows = windows.size();
9640                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
9641                    final WindowState ws = windows.get(winNdx);
9642                    WindowStateAnimator wsa = ws.mWinAnimator;
9643                    if (wsa.mSurfaceControl != null) {
9644                        if (!mSessions.contains(wsa.mSession)) {
9645                            Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): "
9646                                    + ws + " surface=" + wsa.mSurfaceControl
9647                                    + " token=" + ws.mToken
9648                                    + " pid=" + ws.mSession.mPid
9649                                    + " uid=" + ws.mSession.mUid);
9650                            if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null);
9651                            wsa.mSurfaceControl.destroy();
9652                            wsa.mSurfaceShown = false;
9653                            wsa.mSurfaceControl = null;
9654                            ws.mHasSurface = false;
9655                            mForceRemoves.add(ws);
9656                            leakedSurface = true;
9657                        } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) {
9658                            Slog.w(TAG, "LEAKED SURFACE (app token hidden): "
9659                                    + ws + " surface=" + wsa.mSurfaceControl
9660                                    + " token=" + ws.mAppToken);
9661                            if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null);
9662                            wsa.mSurfaceControl.destroy();
9663                            wsa.mSurfaceShown = false;
9664                            wsa.mSurfaceControl = null;
9665                            ws.mHasSurface = false;
9666                            leakedSurface = true;
9667                        }
9668                    }
9669                }
9670            }
9671
9672            if (!leakedSurface) {
9673                Slog.w(TAG, "No leaked surfaces; killing applicatons!");
9674                SparseIntArray pidCandidates = new SparseIntArray();
9675                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9676                    final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
9677                    final int numWindows = windows.size();
9678                    for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
9679                        final WindowState ws = windows.get(winNdx);
9680                        if (mForceRemoves.contains(ws)) {
9681                            continue;
9682                        }
9683                        WindowStateAnimator wsa = ws.mWinAnimator;
9684                        if (wsa.mSurfaceControl != null) {
9685                            pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid);
9686                        }
9687                    }
9688                    if (pidCandidates.size() > 0) {
9689                        int[] pids = new int[pidCandidates.size()];
9690                        for (int i=0; i<pids.length; i++) {
9691                            pids[i] = pidCandidates.keyAt(i);
9692                        }
9693                        try {
9694                            if (mActivityManager.killPids(pids, "Free memory", secure)) {
9695                                killedApps = true;
9696                            }
9697                        } catch (RemoteException e) {
9698                        }
9699                    }
9700                }
9701            }
9702
9703            if (leakedSurface || killedApps) {
9704                // We managed to reclaim some memory, so get rid of the trouble
9705                // surface and ask the app to request another one.
9706                Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry.");
9707                if (surface != null) {
9708                    if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin,
9709                            "RECOVER DESTROY", null);
9710                    surface.destroy();
9711                    winAnimator.mSurfaceShown = false;
9712                    winAnimator.mSurfaceControl = null;
9713                    winAnimator.mWin.mHasSurface = false;
9714                    scheduleRemoveStartingWindow(winAnimator.mWin.mAppToken);
9715                }
9716
9717                try {
9718                    winAnimator.mWin.mClient.dispatchGetNewSurface();
9719                } catch (RemoteException e) {
9720                }
9721            }
9722        } finally {
9723            Binder.restoreCallingIdentity(callingIdentity);
9724        }
9725
9726        return leakedSurface || killedApps;
9727    }
9728
9729    private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
9730        WindowState newFocus = computeFocusedWindowLocked();
9731        if (mCurrentFocus != newFocus) {
9732            Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus");
9733            // This check makes sure that we don't already have the focus
9734            // change message pending.
9735            mH.removeMessages(H.REPORT_FOCUS_CHANGE);
9736            mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
9737            // TODO(multidisplay): Focused windows on default display only.
9738            final DisplayContent displayContent = getDefaultDisplayContentLocked();
9739            final boolean imWindowChanged = moveInputMethodWindowsIfNeededLocked(
9740                    mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS
9741                            && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES);
9742            if (imWindowChanged) {
9743                displayContent.layoutNeeded = true;
9744                newFocus = computeFocusedWindowLocked();
9745            }
9746
9747            if (true || DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG, "Changing focus from " +
9748                    mCurrentFocus + " to " + newFocus + " Callers=" + Debug.getCallers(4));
9749            final WindowState oldFocus = mCurrentFocus;
9750            mCurrentFocus = newFocus;
9751            mLosingFocus.remove(newFocus);
9752            int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
9753
9754            if (imWindowChanged && oldFocus != mInputMethodWindow) {
9755                // Focus of the input method window changed. Perform layout if needed.
9756                if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
9757                    performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows);
9758                    focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9759                } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
9760                    // Client will do the layout, but we need to assign layers
9761                    // for handleNewWindowLocked() below.
9762                    assignLayersLocked(displayContent.getWindowList());
9763                }
9764            }
9765
9766            if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
9767                // The change in focus caused us to need to do a layout.  Okay.
9768                displayContent.layoutNeeded = true;
9769                if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
9770                    performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows);
9771                }
9772            }
9773
9774            if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
9775                // If we defer assigning layers, then the caller is responsible for
9776                // doing this part.
9777                finishUpdateFocusedWindowAfterAssignLayersLocked(updateInputWindows);
9778            }
9779
9780            Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
9781            return true;
9782        }
9783        return false;
9784    }
9785
9786    private void finishUpdateFocusedWindowAfterAssignLayersLocked(boolean updateInputWindows) {
9787        mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows);
9788    }
9789
9790    private WindowState computeFocusedWindowLocked() {
9791        if (mAnimator.mUniverseBackground != null
9792                && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) {
9793            return mAnimator.mUniverseBackground.mWin;
9794        }
9795
9796        final int displayCount = mDisplayContents.size();
9797        for (int i = 0; i < displayCount; i++) {
9798            final DisplayContent displayContent = mDisplayContents.valueAt(i);
9799            WindowState win = findFocusedWindowLocked(displayContent);
9800            if (win != null) {
9801                return win;
9802            }
9803        }
9804        return null;
9805    }
9806
9807    private WindowState findFocusedWindowLocked(DisplayContent displayContent) {
9808        final WindowList windows = displayContent.getWindowList();
9809        for (int i = windows.size() - 1; i >= 0; i--) {
9810            final WindowState win = windows.get(i);
9811
9812            if (localLOGV || DEBUG_FOCUS) Slog.v(
9813                TAG, "Looking for focus: " + i
9814                + " = " + win
9815                + ", flags=" + win.mAttrs.flags
9816                + ", canReceive=" + win.canReceiveKeys());
9817
9818            AppWindowToken wtoken = win.mAppToken;
9819
9820            // If this window's application has been removed, just skip it.
9821            if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) {
9822                if (DEBUG_FOCUS) Slog.v(TAG, "Skipping " + wtoken + " because "
9823                        + (wtoken.removed ? "removed" : "sendingToBottom"));
9824                continue;
9825            }
9826
9827            if (!win.canReceiveKeys()) {
9828                continue;
9829            }
9830
9831            // Descend through all of the app tokens and find the first that either matches
9832            // win.mAppToken (return win) or mFocusedApp (return null).
9833            if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING &&
9834                    mFocusedApp != null) {
9835                ArrayList<Task> tasks = displayContent.getTasks();
9836                for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
9837                    AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
9838                    int tokenNdx = tokens.size() - 1;
9839                    for ( ; tokenNdx >= 0; --tokenNdx) {
9840                        final AppWindowToken token = tokens.get(tokenNdx);
9841                        if (wtoken == token) {
9842                            break;
9843                        }
9844                        if (mFocusedApp == token) {
9845                            // Whoops, we are below the focused app...  no focus for you!
9846                            if (localLOGV || DEBUG_FOCUS_LIGHT) Slog.v(TAG,
9847                                    "findFocusedWindow: Reached focused app=" + mFocusedApp);
9848                            return null;
9849                        }
9850                    }
9851                    if (tokenNdx >= 0) {
9852                        // Early exit from loop, must have found the matching token.
9853                        break;
9854                    }
9855                }
9856            }
9857
9858            if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: Found new focus @ " + i +
9859                        " = " + win);
9860            return win;
9861        }
9862
9863        if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: No focusable windows.");
9864        return null;
9865    }
9866
9867    private void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) {
9868        if (mDisplayFrozen) {
9869            return;
9870        }
9871
9872        if (!mDisplayReady || !mPolicy.isScreenOnFully()) {
9873            // No need to freeze the screen before the system is ready or if
9874            // the screen is off.
9875            return;
9876        }
9877
9878        mScreenFrozenLock.acquire();
9879
9880        mDisplayFrozen = true;
9881        mDisplayFreezeTime = SystemClock.elapsedRealtime();
9882        mLastFinishedFreezeSource = null;
9883
9884        mInputMonitor.freezeInputDispatchingLw();
9885
9886        // Clear the last input window -- that is just used for
9887        // clean transitions between IMEs, and if we are freezing
9888        // the screen then the whole world is changing behind the scenes.
9889        mPolicy.setLastInputMethodWindowLw(null, null);
9890
9891        if (mAppTransition.isTransitionSet()) {
9892            mAppTransition.freeze();
9893        }
9894
9895        if (PROFILE_ORIENTATION) {
9896            File file = new File("/data/system/frozen");
9897            Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
9898        }
9899
9900        if (CUSTOM_SCREEN_ROTATION) {
9901            mExitAnimId = exitAnim;
9902            mEnterAnimId = enterAnim;
9903            final DisplayContent displayContent = getDefaultDisplayContentLocked();
9904            final int displayId = displayContent.getDisplayId();
9905            ScreenRotationAnimation screenRotationAnimation =
9906                    mAnimator.getScreenRotationAnimationLocked(displayId);
9907            if (screenRotationAnimation != null) {
9908                screenRotationAnimation.kill();
9909            }
9910
9911            // TODO(multidisplay): rotation on main screen only.
9912            screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent,
9913                    mFxSession, inTransaction, mPolicy.isDefaultOrientationForced());
9914            mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
9915        }
9916    }
9917
9918    private void stopFreezingDisplayLocked() {
9919        if (!mDisplayFrozen) {
9920            return;
9921        }
9922
9923        if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen
9924                || mClientFreezingScreen) {
9925            if (DEBUG_ORIENTATION) Slog.d(TAG,
9926                "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig
9927                + ", mAppsFreezingScreen=" + mAppsFreezingScreen
9928                + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen
9929                + ", mClientFreezingScreen=" + mClientFreezingScreen);
9930            return;
9931        }
9932
9933        mDisplayFrozen = false;
9934        mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime);
9935        StringBuilder sb = new StringBuilder(128);
9936        sb.append("Screen frozen for ");
9937        TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb);
9938        if (mLastFinishedFreezeSource != null) {
9939            sb.append(" due to ");
9940            sb.append(mLastFinishedFreezeSource);
9941        }
9942        Slog.i(TAG, sb.toString());
9943        mH.removeMessages(H.APP_FREEZE_TIMEOUT);
9944        mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
9945        if (PROFILE_ORIENTATION) {
9946            Debug.stopMethodTracing();
9947        }
9948
9949        boolean updateRotation = false;
9950
9951        final DisplayContent displayContent = getDefaultDisplayContentLocked();
9952        final int displayId = displayContent.getDisplayId();
9953        ScreenRotationAnimation screenRotationAnimation =
9954                mAnimator.getScreenRotationAnimationLocked(displayId);
9955        if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
9956                && screenRotationAnimation.hasScreenshot()) {
9957            if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation");
9958            // TODO(multidisplay): rotation on main screen only.
9959            DisplayInfo displayInfo = displayContent.getDisplayInfo();
9960            // Get rotation animation again, with new top window
9961            boolean isDimming = displayContent.isDimming();
9962            if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) {
9963                mExitAnimId = mEnterAnimId = 0;
9964            }
9965            if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
9966                    mTransitionAnimationScale, displayInfo.logicalWidth,
9967                        displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) {
9968                scheduleAnimationLocked();
9969            } else {
9970                screenRotationAnimation.kill();
9971                screenRotationAnimation = null;
9972                mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
9973                updateRotation = true;
9974            }
9975        } else {
9976            if (screenRotationAnimation != null) {
9977                screenRotationAnimation.kill();
9978                screenRotationAnimation = null;
9979                mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
9980            }
9981            updateRotation = true;
9982        }
9983
9984        mInputMonitor.thawInputDispatchingLw();
9985
9986        boolean configChanged;
9987
9988        // While the display is frozen we don't re-compute the orientation
9989        // to avoid inconsistent states.  However, something interesting
9990        // could have actually changed during that time so re-evaluate it
9991        // now to catch that.
9992        configChanged = updateOrientationFromAppTokensLocked(false);
9993
9994        // A little kludge: a lot could have happened while the
9995        // display was frozen, so now that we are coming back we
9996        // do a gc so that any remote references the system
9997        // processes holds on others can be released if they are
9998        // no longer needed.
9999        mH.removeMessages(H.FORCE_GC);
10000        mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000);
10001
10002        mScreenFrozenLock.release();
10003
10004        if (updateRotation) {
10005            if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
10006            configChanged |= updateRotationUncheckedLocked(false);
10007        }
10008
10009        if (configChanged) {
10010            mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
10011        }
10012    }
10013
10014    static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps,
10015            DisplayMetrics dm) {
10016        if (index < tokens.length) {
10017            String str = tokens[index];
10018            if (str != null && str.length() > 0) {
10019                try {
10020                    int val = Integer.parseInt(str);
10021                    return val;
10022                } catch (Exception e) {
10023                }
10024            }
10025        }
10026        if (defUnits == TypedValue.COMPLEX_UNIT_PX) {
10027            return defDps;
10028        }
10029        int val = (int)TypedValue.applyDimension(defUnits, defDps, dm);
10030        return val;
10031    }
10032
10033    void createWatermarkInTransaction() {
10034        if (mWatermark != null) {
10035            return;
10036        }
10037
10038        File file = new File("/system/etc/setup.conf");
10039        FileInputStream in = null;
10040        DataInputStream ind = null;
10041        try {
10042            in = new FileInputStream(file);
10043            ind = new DataInputStream(in);
10044            String line = ind.readLine();
10045            if (line != null) {
10046                String[] toks = line.split("%");
10047                if (toks != null && toks.length > 0) {
10048                    mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(),
10049                            mRealDisplayMetrics, mFxSession, toks);
10050                }
10051            }
10052        } catch (FileNotFoundException e) {
10053        } catch (IOException e) {
10054        } finally {
10055            if (ind != null) {
10056                try {
10057                    ind.close();
10058                } catch (IOException e) {
10059                }
10060            } else if (in != null) {
10061                try {
10062                    in.close();
10063                } catch (IOException e) {
10064                }
10065            }
10066        }
10067    }
10068
10069    @Override
10070    public void statusBarVisibilityChanged(int visibility) {
10071        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
10072                != PackageManager.PERMISSION_GRANTED) {
10073            throw new SecurityException("Caller does not hold permission "
10074                    + android.Manifest.permission.STATUS_BAR);
10075        }
10076
10077        synchronized (mWindowMap) {
10078            mLastStatusBarVisibility = visibility;
10079            visibility = mPolicy.adjustSystemUiVisibilityLw(visibility);
10080            updateStatusBarVisibilityLocked(visibility);
10081        }
10082    }
10083
10084    // TOOD(multidisplay): StatusBar on multiple screens?
10085    void updateStatusBarVisibilityLocked(int visibility) {
10086        mInputManager.setSystemUiVisibility(visibility);
10087        final WindowList windows = getDefaultWindowListLocked();
10088        final int N = windows.size();
10089        for (int i = 0; i < N; i++) {
10090            WindowState ws = windows.get(i);
10091            try {
10092                int curValue = ws.mSystemUiVisibility;
10093                int diff = curValue ^ visibility;
10094                // We are only interested in differences of one of the
10095                // clearable flags...
10096                diff &= View.SYSTEM_UI_CLEARABLE_FLAGS;
10097                // ...if it has actually been cleared.
10098                diff &= ~visibility;
10099                int newValue = (curValue&~diff) | (visibility&diff);
10100                if (newValue != curValue) {
10101                    ws.mSeq++;
10102                    ws.mSystemUiVisibility = newValue;
10103                }
10104                if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) {
10105                    ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq,
10106                            visibility, newValue, diff);
10107                }
10108            } catch (RemoteException e) {
10109                // so sorry
10110            }
10111        }
10112    }
10113
10114    @Override
10115    public void reevaluateStatusBarVisibility() {
10116        synchronized (mWindowMap) {
10117            int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility);
10118            updateStatusBarVisibilityLocked(visibility);
10119            performLayoutAndPlaceSurfacesLocked();
10120        }
10121    }
10122
10123    @Override
10124    public FakeWindow addFakeWindow(Looper looper,
10125            InputEventReceiver.Factory inputEventReceiverFactory,
10126            String name, int windowType, int layoutParamsFlags, int layoutParamsPrivateFlags,
10127            boolean canReceiveKeys, boolean hasFocus, boolean touchFullscreen) {
10128        synchronized (mWindowMap) {
10129            FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputEventReceiverFactory,
10130                    name, windowType,
10131                    layoutParamsFlags, layoutParamsPrivateFlags, canReceiveKeys,
10132                    hasFocus, touchFullscreen);
10133            int i=0;
10134            while (i<mFakeWindows.size()) {
10135                if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) {
10136                    break;
10137                }
10138            }
10139            mFakeWindows.add(i, fw);
10140            mInputMonitor.updateInputWindowsLw(true);
10141            return fw;
10142        }
10143    }
10144
10145    boolean removeFakeWindowLocked(FakeWindow window) {
10146        synchronized (mWindowMap) {
10147            if (mFakeWindows.remove(window)) {
10148                mInputMonitor.updateInputWindowsLw(true);
10149                return true;
10150            }
10151            return false;
10152        }
10153    }
10154
10155    // It is assumed that this method is called only by InputMethodManagerService.
10156    public void saveLastInputMethodWindowForTransition() {
10157        synchronized (mWindowMap) {
10158            // TODO(multidisplay): Pass in the displayID.
10159            DisplayContent displayContent = getDefaultDisplayContentLocked();
10160            if (mInputMethodWindow != null) {
10161                mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget);
10162            }
10163        }
10164    }
10165
10166    @Override
10167    public boolean hasNavigationBar() {
10168        return mPolicy.hasNavigationBar();
10169    }
10170
10171    @Override
10172    public void lockNow(Bundle options) {
10173        mPolicy.lockNow(options);
10174    }
10175
10176    @Override
10177    public boolean isSafeModeEnabled() {
10178        return mSafeMode;
10179    }
10180
10181    void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) {
10182        pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)");
10183        mPolicy.dump("    ", pw, args);
10184    }
10185
10186    void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) {
10187        pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)");
10188        mAnimator.dumpLocked(pw, "    ", dumpAll);
10189    }
10190
10191    void dumpTokensLocked(PrintWriter pw, boolean dumpAll) {
10192        pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)");
10193        if (mTokenMap.size() > 0) {
10194            pw.println("  All tokens:");
10195            Iterator<WindowToken> it = mTokenMap.values().iterator();
10196            while (it.hasNext()) {
10197                WindowToken token = it.next();
10198                pw.print("  "); pw.print(token);
10199                if (dumpAll) {
10200                    pw.println(':');
10201                    token.dump(pw, "    ");
10202                } else {
10203                    pw.println();
10204                }
10205            }
10206        }
10207        if (mWallpaperTokens.size() > 0) {
10208            pw.println();
10209            pw.println("  Wallpaper tokens:");
10210            for (int i=mWallpaperTokens.size()-1; i>=0; i--) {
10211                WindowToken token = mWallpaperTokens.get(i);
10212                pw.print("  Wallpaper #"); pw.print(i);
10213                        pw.print(' '); pw.print(token);
10214                if (dumpAll) {
10215                    pw.println(':');
10216                    token.dump(pw, "    ");
10217                } else {
10218                    pw.println();
10219                }
10220            }
10221        }
10222        if (mFinishedStarting.size() > 0) {
10223            pw.println();
10224            pw.println("  Finishing start of application tokens:");
10225            for (int i=mFinishedStarting.size()-1; i>=0; i--) {
10226                WindowToken token = mFinishedStarting.get(i);
10227                pw.print("  Finished Starting #"); pw.print(i);
10228                        pw.print(' '); pw.print(token);
10229                if (dumpAll) {
10230                    pw.println(':');
10231                    token.dump(pw, "    ");
10232                } else {
10233                    pw.println();
10234                }
10235            }
10236        }
10237        if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) {
10238            pw.println();
10239            if (mOpeningApps.size() > 0) {
10240                pw.print("  mOpeningApps="); pw.println(mOpeningApps);
10241            }
10242            if (mClosingApps.size() > 0) {
10243                pw.print("  mClosingApps="); pw.println(mClosingApps);
10244            }
10245        }
10246    }
10247
10248    void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) {
10249        pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)");
10250        if (mSessions.size() > 0) {
10251            Iterator<Session> it = mSessions.iterator();
10252            while (it.hasNext()) {
10253                Session s = it.next();
10254                pw.print("  Session "); pw.print(s); pw.println(':');
10255                s.dump(pw, "    ");
10256            }
10257        }
10258    }
10259
10260    void dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll) {
10261        pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)");
10262        if (mDisplayReady) {
10263            final int numDisplays = mDisplayContents.size();
10264            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10265                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
10266                displayContent.dump("  ", pw);
10267            }
10268        } else {
10269            pw.println("  NO DISPLAY");
10270        }
10271    }
10272
10273    void dumpWindowsLocked(PrintWriter pw, boolean dumpAll,
10274            ArrayList<WindowState> windows) {
10275        pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)");
10276        dumpWindowsNoHeaderLocked(pw, dumpAll, windows);
10277    }
10278
10279    void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll,
10280            ArrayList<WindowState> windows) {
10281        final int numDisplays = mDisplayContents.size();
10282        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10283            final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList();
10284            for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10285                final WindowState w = windowList.get(winNdx);
10286                if (windows == null || windows.contains(w)) {
10287                    pw.print("  Window #"); pw.print(winNdx); pw.print(' ');
10288                            pw.print(w); pw.println(":");
10289                    w.dump(pw, "    ", dumpAll || windows != null);
10290                }
10291            }
10292        }
10293        if (mInputMethodDialogs.size() > 0) {
10294            pw.println();
10295            pw.println("  Input method dialogs:");
10296            for (int i=mInputMethodDialogs.size()-1; i>=0; i--) {
10297                WindowState w = mInputMethodDialogs.get(i);
10298                if (windows == null || windows.contains(w)) {
10299                    pw.print("  IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w);
10300                }
10301            }
10302        }
10303        if (mPendingRemove.size() > 0) {
10304            pw.println();
10305            pw.println("  Remove pending for:");
10306            for (int i=mPendingRemove.size()-1; i>=0; i--) {
10307                WindowState w = mPendingRemove.get(i);
10308                if (windows == null || windows.contains(w)) {
10309                    pw.print("  Remove #"); pw.print(i); pw.print(' ');
10310                            pw.print(w);
10311                    if (dumpAll) {
10312                        pw.println(":");
10313                        w.dump(pw, "    ", true);
10314                    } else {
10315                        pw.println();
10316                    }
10317                }
10318            }
10319        }
10320        if (mForceRemoves != null && mForceRemoves.size() > 0) {
10321            pw.println();
10322            pw.println("  Windows force removing:");
10323            for (int i=mForceRemoves.size()-1; i>=0; i--) {
10324                WindowState w = mForceRemoves.get(i);
10325                pw.print("  Removing #"); pw.print(i); pw.print(' ');
10326                        pw.print(w);
10327                if (dumpAll) {
10328                    pw.println(":");
10329                    w.dump(pw, "    ", true);
10330                } else {
10331                    pw.println();
10332                }
10333            }
10334        }
10335        if (mDestroySurface.size() > 0) {
10336            pw.println();
10337            pw.println("  Windows waiting to destroy their surface:");
10338            for (int i=mDestroySurface.size()-1; i>=0; i--) {
10339                WindowState w = mDestroySurface.get(i);
10340                if (windows == null || windows.contains(w)) {
10341                    pw.print("  Destroy #"); pw.print(i); pw.print(' ');
10342                            pw.print(w);
10343                    if (dumpAll) {
10344                        pw.println(":");
10345                        w.dump(pw, "    ", true);
10346                    } else {
10347                        pw.println();
10348                    }
10349                }
10350            }
10351        }
10352        if (mLosingFocus.size() > 0) {
10353            pw.println();
10354            pw.println("  Windows losing focus:");
10355            for (int i=mLosingFocus.size()-1; i>=0; i--) {
10356                WindowState w = mLosingFocus.get(i);
10357                if (windows == null || windows.contains(w)) {
10358                    pw.print("  Losing #"); pw.print(i); pw.print(' ');
10359                            pw.print(w);
10360                    if (dumpAll) {
10361                        pw.println(":");
10362                        w.dump(pw, "    ", true);
10363                    } else {
10364                        pw.println();
10365                    }
10366                }
10367            }
10368        }
10369        if (mResizingWindows.size() > 0) {
10370            pw.println();
10371            pw.println("  Windows waiting to resize:");
10372            for (int i=mResizingWindows.size()-1; i>=0; i--) {
10373                WindowState w = mResizingWindows.get(i);
10374                if (windows == null || windows.contains(w)) {
10375                    pw.print("  Resizing #"); pw.print(i); pw.print(' ');
10376                            pw.print(w);
10377                    if (dumpAll) {
10378                        pw.println(":");
10379                        w.dump(pw, "    ", true);
10380                    } else {
10381                        pw.println();
10382                    }
10383                }
10384            }
10385        }
10386        if (mWaitingForDrawn.size() > 0) {
10387            pw.println();
10388            pw.println("  Clients waiting for these windows to be drawn:");
10389            for (int i=mWaitingForDrawn.size()-1; i>=0; i--) {
10390                Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(i);
10391                pw.print("  Waiting #"); pw.print(i); pw.print(' '); pw.print(pair.first);
10392                        pw.print(": "); pw.println(pair.second);
10393            }
10394        }
10395        pw.println();
10396        pw.print("  mCurConfiguration="); pw.println(this.mCurConfiguration);
10397        pw.print("  mCurrentFocus="); pw.println(mCurrentFocus);
10398        if (mLastFocus != mCurrentFocus) {
10399            pw.print("  mLastFocus="); pw.println(mLastFocus);
10400        }
10401        pw.print("  mFocusedApp="); pw.println(mFocusedApp);
10402        if (mInputMethodTarget != null) {
10403            pw.print("  mInputMethodTarget="); pw.println(mInputMethodTarget);
10404        }
10405        pw.print("  mInTouchMode="); pw.print(mInTouchMode);
10406                pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
10407        pw.print("  mLastDisplayFreezeDuration=");
10408                TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw);
10409                if ( mLastFinishedFreezeSource != null) {
10410                    pw.print(" due to ");
10411                    pw.print(mLastFinishedFreezeSource);
10412                }
10413                pw.println();
10414        if (dumpAll) {
10415            pw.print(" mSystemDecorLayer="); pw.print(mSystemDecorLayer);
10416                    pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString());
10417            if (mLastStatusBarVisibility != 0) {
10418                pw.print("  mLastStatusBarVisibility=0x");
10419                        pw.println(Integer.toHexString(mLastStatusBarVisibility));
10420            }
10421            if (mInputMethodWindow != null) {
10422                pw.print("  mInputMethodWindow="); pw.println(mInputMethodWindow);
10423            }
10424            pw.print("  mWallpaperTarget="); pw.println(mWallpaperTarget);
10425            if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) {
10426                pw.print("  mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget);
10427                pw.print("  mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget);
10428            }
10429            pw.print("  mLastWallpaperX="); pw.print(mLastWallpaperX);
10430                    pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
10431            if (mInputMethodAnimLayerAdjustment != 0 ||
10432                    mWallpaperAnimLayerAdjustment != 0) {
10433                pw.print("  mInputMethodAnimLayerAdjustment=");
10434                        pw.print(mInputMethodAnimLayerAdjustment);
10435                        pw.print("  mWallpaperAnimLayerAdjustment=");
10436                        pw.println(mWallpaperAnimLayerAdjustment);
10437            }
10438            pw.print("  mSystemBooted="); pw.print(mSystemBooted);
10439                    pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
10440            if (needsLayout()) {
10441                pw.print("  layoutNeeded on displays=");
10442                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10443                    final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
10444                    if (displayContent.layoutNeeded) {
10445                        pw.print(displayContent.getDisplayId());
10446                    }
10447                }
10448                pw.println();
10449            }
10450            pw.print("  mTransactionSequence="); pw.println(mTransactionSequence);
10451            pw.print("  mDisplayFrozen="); pw.print(mDisplayFrozen);
10452                    pw.print(" windows="); pw.print(mWindowsFreezingScreen);
10453                    pw.print(" client="); pw.print(mClientFreezingScreen);
10454                    pw.print(" apps="); pw.print(mAppsFreezingScreen);
10455                    pw.print(" waitingForConfig="); pw.println(mWaitingForConfig);
10456            pw.print("  mRotation="); pw.print(mRotation);
10457                    pw.print(" mAltOrientation="); pw.println(mAltOrientation);
10458            pw.print("  mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation);
10459                    pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation);
10460            pw.print("  mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount);
10461            pw.print("  mWindowAnimationScale="); pw.print(mWindowAnimationScale);
10462                    pw.print(" mTransitionWindowAnimationScale="); pw.print(mTransitionAnimationScale);
10463                    pw.print(" mAnimatorDurationScale="); pw.println(mAnimatorDurationScale);
10464            pw.print("  mTraversalScheduled="); pw.println(mTraversalScheduled);
10465            pw.print("  mStartingIconInTransition="); pw.print(mStartingIconInTransition);
10466                    pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
10467            pw.println("  mLayoutToAnim:");
10468            mAppTransition.dump(pw);
10469        }
10470    }
10471
10472    boolean dumpWindows(PrintWriter pw, String name, String[] args,
10473            int opti, boolean dumpAll) {
10474        WindowList windows = new WindowList();
10475        if ("visible".equals(name)) {
10476            synchronized(mWindowMap) {
10477                final int numDisplays = mDisplayContents.size();
10478                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10479                    final WindowList windowList =
10480                            mDisplayContents.valueAt(displayNdx).getWindowList();
10481                    for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10482                        final WindowState w = windowList.get(winNdx);
10483                        if (w.mWinAnimator.mSurfaceShown) {
10484                            windows.add(w);
10485                        }
10486                    }
10487                }
10488            }
10489        } else {
10490            int objectId = 0;
10491            // See if this is an object ID.
10492            try {
10493                objectId = Integer.parseInt(name, 16);
10494                name = null;
10495            } catch (RuntimeException e) {
10496            }
10497            synchronized(mWindowMap) {
10498                final int numDisplays = mDisplayContents.size();
10499                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10500                    final WindowList windowList =
10501                            mDisplayContents.valueAt(displayNdx).getWindowList();
10502                    for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10503                        final WindowState w = windowList.get(winNdx);
10504                        if (name != null) {
10505                            if (w.mAttrs.getTitle().toString().contains(name)) {
10506                                windows.add(w);
10507                            }
10508                        } else if (System.identityHashCode(w) == objectId) {
10509                            windows.add(w);
10510                        }
10511                    }
10512                }
10513            }
10514        }
10515
10516        if (windows.size() <= 0) {
10517            return false;
10518        }
10519
10520        synchronized(mWindowMap) {
10521            dumpWindowsLocked(pw, dumpAll, windows);
10522        }
10523        return true;
10524    }
10525
10526    void dumpLastANRLocked(PrintWriter pw) {
10527        pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)");
10528        if (mLastANRState == null) {
10529            pw.println("  <no ANR has occurred since boot>");
10530        } else {
10531            pw.println(mLastANRState);
10532        }
10533    }
10534
10535    /**
10536     * Saves information about the state of the window manager at
10537     * the time an ANR occurred before anything else in the system changes
10538     * in response.
10539     *
10540     * @param appWindowToken The application that ANR'd, may be null.
10541     * @param windowState The window that ANR'd, may be null.
10542     * @param reason The reason for the ANR, may be null.
10543     */
10544    public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState,
10545            String reason) {
10546        StringWriter sw = new StringWriter();
10547        PrintWriter pw = new FastPrintWriter(sw, false, 1024);
10548        pw.println("  ANR time: " + DateFormat.getInstance().format(new Date()));
10549        if (appWindowToken != null) {
10550            pw.println("  Application at fault: " + appWindowToken.stringName);
10551        }
10552        if (windowState != null) {
10553            pw.println("  Window at fault: " + windowState.mAttrs.getTitle());
10554        }
10555        if (reason != null) {
10556            pw.println("  Reason: " + reason);
10557        }
10558        pw.println();
10559        dumpWindowsNoHeaderLocked(pw, true, null);
10560        pw.close();
10561        mLastANRState = sw.toString();
10562    }
10563
10564    @Override
10565    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
10566        if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
10567                != PackageManager.PERMISSION_GRANTED) {
10568            pw.println("Permission Denial: can't dump WindowManager from from pid="
10569                    + Binder.getCallingPid()
10570                    + ", uid=" + Binder.getCallingUid());
10571            return;
10572        }
10573
10574        boolean dumpAll = false;
10575
10576        int opti = 0;
10577        while (opti < args.length) {
10578            String opt = args[opti];
10579            if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
10580                break;
10581            }
10582            opti++;
10583            if ("-a".equals(opt)) {
10584                dumpAll = true;
10585            } else if ("-h".equals(opt)) {
10586                pw.println("Window manager dump options:");
10587                pw.println("  [-a] [-h] [cmd] ...");
10588                pw.println("  cmd may be one of:");
10589                pw.println("    l[astanr]: last ANR information");
10590                pw.println("    p[policy]: policy state");
10591                pw.println("    a[animator]: animator state");
10592                pw.println("    s[essions]: active sessions");
10593                pw.println("    d[isplays]: active display contents");
10594                pw.println("    t[okens]: token list");
10595                pw.println("    w[indows]: window list");
10596                pw.println("  cmd may also be a NAME to dump windows.  NAME may");
10597                pw.println("    be a partial substring in a window name, a");
10598                pw.println("    Window hex object identifier, or");
10599                pw.println("    \"all\" for all windows, or");
10600                pw.println("    \"visible\" for the visible windows.");
10601                pw.println("  -a: include all available server state.");
10602                return;
10603            } else {
10604                pw.println("Unknown argument: " + opt + "; use -h for help");
10605            }
10606        }
10607
10608        // Is the caller requesting to dump a particular piece of data?
10609        if (opti < args.length) {
10610            String cmd = args[opti];
10611            opti++;
10612            if ("lastanr".equals(cmd) || "l".equals(cmd)) {
10613                synchronized(mWindowMap) {
10614                    dumpLastANRLocked(pw);
10615                }
10616                return;
10617            } else if ("policy".equals(cmd) || "p".equals(cmd)) {
10618                synchronized(mWindowMap) {
10619                    dumpPolicyLocked(pw, args, true);
10620                }
10621                return;
10622            } else if ("animator".equals(cmd) || "a".equals(cmd)) {
10623                synchronized(mWindowMap) {
10624                    dumpAnimatorLocked(pw, args, true);
10625                }
10626                return;
10627            } else if ("sessions".equals(cmd) || "s".equals(cmd)) {
10628                synchronized(mWindowMap) {
10629                    dumpSessionsLocked(pw, true);
10630                }
10631                return;
10632            } else if ("displays".equals(cmd) || "d".equals(cmd)) {
10633                synchronized(mWindowMap) {
10634                    dumpDisplayContentsLocked(pw, true);
10635                }
10636                return;
10637            } else if ("tokens".equals(cmd) || "t".equals(cmd)) {
10638                synchronized(mWindowMap) {
10639                    dumpTokensLocked(pw, true);
10640                }
10641                return;
10642            } else if ("windows".equals(cmd) || "w".equals(cmd)) {
10643                synchronized(mWindowMap) {
10644                    dumpWindowsLocked(pw, true, null);
10645                }
10646                return;
10647            } else if ("all".equals(cmd) || "a".equals(cmd)) {
10648                synchronized(mWindowMap) {
10649                    dumpWindowsLocked(pw, true, null);
10650                }
10651                return;
10652            } else {
10653                // Dumping a single name?
10654                if (!dumpWindows(pw, cmd, args, opti, dumpAll)) {
10655                    pw.println("Bad window command, or no windows match: " + cmd);
10656                    pw.println("Use -h for help.");
10657                }
10658                return;
10659            }
10660        }
10661
10662        synchronized(mWindowMap) {
10663            pw.println();
10664            if (dumpAll) {
10665                pw.println("-------------------------------------------------------------------------------");
10666            }
10667            dumpLastANRLocked(pw);
10668            pw.println();
10669            if (dumpAll) {
10670                pw.println("-------------------------------------------------------------------------------");
10671            }
10672            dumpPolicyLocked(pw, args, dumpAll);
10673            pw.println();
10674            if (dumpAll) {
10675                pw.println("-------------------------------------------------------------------------------");
10676            }
10677            dumpAnimatorLocked(pw, args, dumpAll);
10678            pw.println();
10679            if (dumpAll) {
10680                pw.println("-------------------------------------------------------------------------------");
10681            }
10682            dumpSessionsLocked(pw, dumpAll);
10683            pw.println();
10684            if (dumpAll) {
10685                pw.println("-------------------------------------------------------------------------------");
10686            }
10687            dumpDisplayContentsLocked(pw, dumpAll);
10688            pw.println();
10689            if (dumpAll) {
10690                pw.println("-------------------------------------------------------------------------------");
10691            }
10692            dumpTokensLocked(pw, dumpAll);
10693            pw.println();
10694            if (dumpAll) {
10695                pw.println("-------------------------------------------------------------------------------");
10696            }
10697            dumpWindowsLocked(pw, dumpAll, null);
10698        }
10699    }
10700
10701    // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection).
10702    @Override
10703    public void monitor() {
10704        synchronized (mWindowMap) { }
10705    }
10706
10707    public interface OnHardKeyboardStatusChangeListener {
10708        public void onHardKeyboardStatusChange(boolean available, boolean enabled);
10709    }
10710
10711    void debugLayoutRepeats(final String msg, int pendingLayoutChanges) {
10712        if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) {
10713            Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" +
10714                    Integer.toHexString(pendingLayoutChanges));
10715        }
10716    }
10717
10718    private DisplayContent newDisplayContentLocked(final Display display) {
10719        DisplayContent displayContent = new DisplayContent(display, this);
10720        final int displayId = display.getDisplayId();
10721        mDisplayContents.put(displayId, displayContent);
10722
10723        DisplayInfo displayInfo = displayContent.getDisplayInfo();
10724        final Rect rect = new Rect();
10725        mDisplaySettings.getOverscanLocked(displayInfo.name, rect);
10726        synchronized (displayContent.mDisplaySizeLock) {
10727            displayInfo.overscanLeft = rect.left;
10728            displayInfo.overscanTop = rect.top;
10729            displayInfo.overscanRight = rect.right;
10730            displayInfo.overscanBottom = rect.bottom;
10731            mDisplayManagerService.setDisplayInfoOverrideFromWindowManager(
10732                    displayId, displayInfo);
10733        }
10734        configureDisplayPolicyLocked(displayContent);
10735
10736        // TODO: Create an input channel for each display with touch capability.
10737        if (displayId == Display.DEFAULT_DISPLAY) {
10738            displayContent.mTapDetector = new StackTapPointerEventListener(this, displayContent);
10739            registerPointerEventListener(displayContent.mTapDetector);
10740        }
10741
10742        return displayContent;
10743    }
10744
10745    public void createDisplayContentLocked(final Display display) {
10746        if (display == null) {
10747            throw new IllegalArgumentException("getDisplayContent: display must not be null");
10748        }
10749        getDisplayContentLocked(display.getDisplayId());
10750    }
10751
10752    /**
10753     * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if
10754     * there is a Display for the displayId.
10755     * @param displayId The display the caller is interested in.
10756     * @return The DisplayContent associated with displayId or null if there is no Display for it.
10757     */
10758    public DisplayContent getDisplayContentLocked(final int displayId) {
10759        DisplayContent displayContent = mDisplayContents.get(displayId);
10760        if (displayContent == null) {
10761            final Display display = mDisplayManager.getDisplay(displayId);
10762            if (display != null) {
10763                displayContent = newDisplayContentLocked(display);
10764            }
10765        }
10766        return displayContent;
10767    }
10768
10769    // There is an inherent assumption that this will never return null.
10770    public DisplayContent getDefaultDisplayContentLocked() {
10771        return getDisplayContentLocked(Display.DEFAULT_DISPLAY);
10772    }
10773
10774    public WindowList getDefaultWindowListLocked() {
10775        return getDefaultDisplayContentLocked().getWindowList();
10776    }
10777
10778    public DisplayInfo getDefaultDisplayInfoLocked() {
10779        return getDefaultDisplayContentLocked().getDisplayInfo();
10780    }
10781
10782    /**
10783     * Return the list of WindowStates associated on the passed display.
10784     * @param display The screen to return windows from.
10785     * @return The list of WindowStates on the screen, or null if the there is no screen.
10786     */
10787    public WindowList getWindowListLocked(final Display display) {
10788        return getWindowListLocked(display.getDisplayId());
10789    }
10790
10791    /**
10792     * Return the list of WindowStates associated on the passed display.
10793     * @param displayId The screen to return windows from.
10794     * @return The list of WindowStates on the screen, or null if the there is no screen.
10795     */
10796    public WindowList getWindowListLocked(final int displayId) {
10797        final DisplayContent displayContent = getDisplayContentLocked(displayId);
10798        return displayContent != null ? displayContent.getWindowList() : null;
10799    }
10800
10801    @Override
10802    public void onDisplayAdded(int displayId) {
10803        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0));
10804    }
10805
10806    private void handleDisplayAddedLocked(int displayId) {
10807        final Display display = mDisplayManager.getDisplay(displayId);
10808        if (display != null) {
10809            createDisplayContentLocked(display);
10810            displayReady(displayId);
10811        }
10812    }
10813
10814    @Override
10815    public void onDisplayRemoved(int displayId) {
10816        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0));
10817    }
10818
10819    private void handleDisplayRemovedLocked(int displayId) {
10820        final DisplayContent displayContent = getDisplayContentLocked(displayId);
10821        if (displayContent != null) {
10822            mDisplayContents.delete(displayId);
10823            displayContent.close();
10824            if (displayId == Display.DEFAULT_DISPLAY) {
10825                unregisterPointerEventListener(displayContent.mTapDetector);
10826            }
10827            WindowList windows = displayContent.getWindowList();
10828            while (!windows.isEmpty()) {
10829                final WindowState win = windows.get(windows.size() - 1);
10830                removeWindowLocked(win.mSession, win);
10831            }
10832        }
10833        mAnimator.removeDisplayLocked(displayId);
10834    }
10835
10836    @Override
10837    public void onDisplayChanged(int displayId) {
10838        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0));
10839    }
10840
10841    private void handleDisplayChangedLocked(int displayId) {
10842        final DisplayContent displayContent = getDisplayContentLocked(displayId);
10843        if (displayContent != null) {
10844            displayContent.updateDisplayInfo();
10845        }
10846    }
10847
10848    @Override
10849    public Object getWindowManagerLock() {
10850        return mWindowMap;
10851    }
10852}
10853