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