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