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