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