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