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