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