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