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