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