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