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