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