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