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