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