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