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