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