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