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