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