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