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