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