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