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