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