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