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