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