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