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