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