WindowManagerService.java revision 6ee618509a392adb183c2e70390cd9e2031ff0d8
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        task.mStack.removeTask(task);
5204        mTaskIdToTask.delete(task.taskId);
5205    }
5206
5207    public void removeTask(int taskId) {
5208        synchronized (mWindowMap) {
5209            Task task = mTaskIdToTask.get(taskId);
5210            if (task == null) {
5211                if (DEBUG_STACK) Slog.i(TAG, "removeTask: could not find taskId=" + taskId);
5212                return;
5213            }
5214            removeTaskLocked(task);
5215        }
5216    }
5217
5218    public void addTask(int taskId, int stackId, boolean toTop) {
5219        synchronized (mWindowMap) {
5220            if (DEBUG_STACK) Slog.i(TAG, "addTask: adding taskId=" + taskId
5221                    + " to " + (toTop ? "top" : "bottom"));
5222            Task task = mTaskIdToTask.get(taskId);
5223            if (task == null) {
5224                return;
5225            }
5226            TaskStack stack = mStackIdToStack.get(stackId);
5227            stack.addTask(task, toTop);
5228            final DisplayContent displayContent = stack.getDisplayContent();
5229            displayContent.layoutNeeded = true;
5230            performLayoutAndPlaceSurfacesLocked();
5231        }
5232    }
5233
5234    public void resizeStack(int stackId, Rect bounds) {
5235        synchronized (mWindowMap) {
5236            final TaskStack stack = mStackIdToStack.get(stackId);
5237            if (stack == null) {
5238                throw new IllegalArgumentException("resizeStack: stackId " + stackId
5239                        + " not found.");
5240            }
5241            if (stack.setBounds(bounds)) {
5242                stack.resizeWindows();
5243                stack.getDisplayContent().layoutNeeded = true;
5244                performLayoutAndPlaceSurfacesLocked();
5245            }
5246        }
5247    }
5248
5249    public void getStackBounds(int stackId, Rect bounds) {
5250        final TaskStack stack = mStackIdToStack.get(stackId);
5251        if (stack != null) {
5252            stack.getBounds(bounds);
5253            return;
5254        }
5255        bounds.setEmpty();
5256    }
5257
5258    // -------------------------------------------------------------
5259    // Misc IWindowSession methods
5260    // -------------------------------------------------------------
5261
5262    @Override
5263    public void startFreezingScreen(int exitAnim, int enterAnim) {
5264        if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
5265                "startFreezingScreen()")) {
5266            throw new SecurityException("Requires FREEZE_SCREEN permission");
5267        }
5268
5269        synchronized(mWindowMap) {
5270            if (!mClientFreezingScreen) {
5271                mClientFreezingScreen = true;
5272                final long origId = Binder.clearCallingIdentity();
5273                try {
5274                    startFreezingDisplayLocked(false, exitAnim, enterAnim);
5275                    mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
5276                    mH.sendEmptyMessageDelayed(H.CLIENT_FREEZE_TIMEOUT, 5000);
5277                } finally {
5278                    Binder.restoreCallingIdentity(origId);
5279                }
5280            }
5281        }
5282    }
5283
5284    @Override
5285    public void stopFreezingScreen() {
5286        if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
5287                "stopFreezingScreen()")) {
5288            throw new SecurityException("Requires FREEZE_SCREEN permission");
5289        }
5290
5291        synchronized(mWindowMap) {
5292            if (mClientFreezingScreen) {
5293                mClientFreezingScreen = false;
5294                mLastFinishedFreezeSource = "client";
5295                final long origId = Binder.clearCallingIdentity();
5296                try {
5297                    stopFreezingDisplayLocked();
5298                } finally {
5299                    Binder.restoreCallingIdentity(origId);
5300                }
5301            }
5302        }
5303    }
5304
5305    @Override
5306    public void disableKeyguard(IBinder token, String tag) {
5307        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5308            != PackageManager.PERMISSION_GRANTED) {
5309            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5310        }
5311
5312        if (token == null) {
5313            throw new IllegalArgumentException("token == null");
5314        }
5315
5316        mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
5317                KeyguardDisableHandler.KEYGUARD_DISABLE, new Pair<IBinder, String>(token, tag)));
5318    }
5319
5320    @Override
5321    public void reenableKeyguard(IBinder token) {
5322        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5323            != PackageManager.PERMISSION_GRANTED) {
5324            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5325        }
5326
5327        if (token == null) {
5328            throw new IllegalArgumentException("token == null");
5329        }
5330
5331        mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
5332                KeyguardDisableHandler.KEYGUARD_REENABLE, token));
5333    }
5334
5335    /**
5336     * @see android.app.KeyguardManager#exitKeyguardSecurely
5337     */
5338    @Override
5339    public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) {
5340        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5341            != PackageManager.PERMISSION_GRANTED) {
5342            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5343        }
5344
5345        if (callback == null) {
5346            throw new IllegalArgumentException("callback == null");
5347        }
5348
5349        mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() {
5350            @Override
5351            public void onKeyguardExitResult(boolean success) {
5352                try {
5353                    callback.onKeyguardExitResult(success);
5354                } catch (RemoteException e) {
5355                    // Client has died, we don't care.
5356                }
5357            }
5358        });
5359    }
5360
5361    @Override
5362    public boolean inKeyguardRestrictedInputMode() {
5363        return mPolicy.inKeyguardRestrictedKeyInputMode();
5364    }
5365
5366    @Override
5367    public boolean isKeyguardLocked() {
5368        return mPolicy.isKeyguardLocked();
5369    }
5370
5371    @Override
5372    public boolean isKeyguardSecure() {
5373        return mPolicy.isKeyguardSecure();
5374    }
5375
5376    @Override
5377    public void dismissKeyguard() {
5378        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5379                != PackageManager.PERMISSION_GRANTED) {
5380            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5381        }
5382        synchronized(mWindowMap) {
5383            mPolicy.dismissKeyguardLw();
5384        }
5385    }
5386
5387    @Override
5388    public void keyguardGoingAway(boolean disableWindowAnimations,
5389            boolean keyguardGoingToNotificationShade) {
5390        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5391                != PackageManager.PERMISSION_GRANTED) {
5392            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5393        }
5394        if (DEBUG_KEYGUARD) Slog.d(TAG, "keyguardGoingAway: disableWinAnim="
5395                + disableWindowAnimations + " kgToNotifShade=" + keyguardGoingToNotificationShade);
5396        synchronized (mWindowMap) {
5397            mAnimator.mKeyguardGoingAway = true;
5398            mAnimator.mKeyguardGoingAwayToNotificationShade = keyguardGoingToNotificationShade;
5399            mAnimator.mKeyguardGoingAwayDisableWindowAnimations = disableWindowAnimations;
5400            requestTraversalLocked();
5401        }
5402    }
5403
5404    public void keyguardWaitingForActivityDrawn() {
5405        if (DEBUG_KEYGUARD) Slog.d(TAG, "keyguardWaitingForActivityDrawn");
5406        synchronized (mWindowMap) {
5407            mKeyguardWaitingForActivityDrawn = true;
5408        }
5409    }
5410
5411    public void notifyActivityDrawnForKeyguard() {
5412        if (DEBUG_KEYGUARD) Slog.d(TAG, "notifyActivityDrawnForKeyguard: waiting="
5413                + mKeyguardWaitingForActivityDrawn + " Callers=" + Debug.getCallers(5));
5414        synchronized (mWindowMap) {
5415            if (mKeyguardWaitingForActivityDrawn) {
5416                mPolicy.notifyActivityDrawnForKeyguardLw();
5417                mKeyguardWaitingForActivityDrawn = false;
5418            }
5419        }
5420    }
5421
5422    void showGlobalActions() {
5423        mPolicy.showGlobalActions();
5424    }
5425
5426    @Override
5427    public void closeSystemDialogs(String reason) {
5428        synchronized(mWindowMap) {
5429            final int numDisplays = mDisplayContents.size();
5430            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5431                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
5432                final int numWindows = windows.size();
5433                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
5434                    final WindowState w = windows.get(winNdx);
5435                    if (w.mHasSurface) {
5436                        try {
5437                            w.mClient.closeSystemDialogs(reason);
5438                        } catch (RemoteException e) {
5439                        }
5440                    }
5441                }
5442            }
5443        }
5444    }
5445
5446    static float fixScale(float scale) {
5447        if (scale < 0) scale = 0;
5448        else if (scale > 20) scale = 20;
5449        return Math.abs(scale);
5450    }
5451
5452    @Override
5453    public void setAnimationScale(int which, float scale) {
5454        if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
5455                "setAnimationScale()")) {
5456            throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
5457        }
5458
5459        scale = fixScale(scale);
5460        switch (which) {
5461            case 0: mWindowAnimationScaleSetting = scale; break;
5462            case 1: mTransitionAnimationScaleSetting = scale; break;
5463            case 2: mAnimatorDurationScaleSetting = scale; break;
5464        }
5465
5466        // Persist setting
5467        mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
5468    }
5469
5470    @Override
5471    public void setAnimationScales(float[] scales) {
5472        if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
5473                "setAnimationScale()")) {
5474            throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
5475        }
5476
5477        if (scales != null) {
5478            if (scales.length >= 1) {
5479                mWindowAnimationScaleSetting = fixScale(scales[0]);
5480            }
5481            if (scales.length >= 2) {
5482                mTransitionAnimationScaleSetting = fixScale(scales[1]);
5483            }
5484            if (scales.length >= 3) {
5485                mAnimatorDurationScaleSetting = fixScale(scales[2]);
5486                dispatchNewAnimatorScaleLocked(null);
5487            }
5488        }
5489
5490        // Persist setting
5491        mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
5492    }
5493
5494    private void setAnimatorDurationScale(float scale) {
5495        mAnimatorDurationScaleSetting = scale;
5496        ValueAnimator.setDurationScale(scale);
5497    }
5498
5499    public float getWindowAnimationScaleLocked() {
5500        return mAnimationsDisabled ? 0 : mWindowAnimationScaleSetting;
5501    }
5502
5503    public float getTransitionAnimationScaleLocked() {
5504        return mAnimationsDisabled ? 0 : mTransitionAnimationScaleSetting;
5505    }
5506
5507    @Override
5508    public float getAnimationScale(int which) {
5509        switch (which) {
5510            case 0: return mWindowAnimationScaleSetting;
5511            case 1: return mTransitionAnimationScaleSetting;
5512            case 2: return mAnimatorDurationScaleSetting;
5513        }
5514        return 0;
5515    }
5516
5517    @Override
5518    public float[] getAnimationScales() {
5519        return new float[] { mWindowAnimationScaleSetting, mTransitionAnimationScaleSetting,
5520                mAnimatorDurationScaleSetting };
5521    }
5522
5523    @Override
5524    public float getCurrentAnimatorScale() {
5525        synchronized(mWindowMap) {
5526            return mAnimationsDisabled ? 0 : mAnimatorDurationScaleSetting;
5527        }
5528    }
5529
5530    void dispatchNewAnimatorScaleLocked(Session session) {
5531        mH.obtainMessage(H.NEW_ANIMATOR_SCALE, session).sendToTarget();
5532    }
5533
5534    @Override
5535    public void registerPointerEventListener(PointerEventListener listener) {
5536        mPointerEventDispatcher.registerInputEventListener(listener);
5537    }
5538
5539    @Override
5540    public void unregisterPointerEventListener(PointerEventListener listener) {
5541        mPointerEventDispatcher.unregisterInputEventListener(listener);
5542    }
5543
5544    // Called by window manager policy. Not exposed externally.
5545    @Override
5546    public int getLidState() {
5547        int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY,
5548                InputManagerService.SW_LID);
5549        if (sw > 0) {
5550            // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL.
5551            return LID_CLOSED;
5552        } else if (sw == 0) {
5553            // Switch state: AKEY_STATE_UP.
5554            return LID_OPEN;
5555        } else {
5556            // Switch state: AKEY_STATE_UNKNOWN.
5557            return LID_ABSENT;
5558        }
5559    }
5560
5561    // Called by window manager policy. Not exposed externally.
5562    @Override
5563    public int getCameraLensCoverState() {
5564        int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY,
5565                InputManagerService.SW_CAMERA_LENS_COVER);
5566        if (sw > 0) {
5567            // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL.
5568            return CAMERA_LENS_COVERED;
5569        } else if (sw == 0) {
5570            // Switch state: AKEY_STATE_UP.
5571            return CAMERA_LENS_UNCOVERED;
5572        } else {
5573            // Switch state: AKEY_STATE_UNKNOWN.
5574            return CAMERA_LENS_COVER_ABSENT;
5575        }
5576    }
5577
5578    // Called by window manager policy.  Not exposed externally.
5579    @Override
5580    public void switchKeyboardLayout(int deviceId, int direction) {
5581        mInputManager.switchKeyboardLayout(deviceId, direction);
5582    }
5583
5584    // Called by window manager policy.  Not exposed externally.
5585    @Override
5586    public void shutdown(boolean confirm) {
5587        ShutdownThread.shutdown(mContext, confirm);
5588    }
5589
5590    // Called by window manager policy.  Not exposed externally.
5591    @Override
5592    public void rebootSafeMode(boolean confirm) {
5593        ShutdownThread.rebootSafeMode(mContext, confirm);
5594    }
5595
5596    public void setCurrentProfileIds(final int[] currentProfileIds) {
5597        synchronized (mWindowMap) {
5598            mCurrentProfileIds = currentProfileIds;
5599        }
5600    }
5601
5602    public void setCurrentUser(final int newUserId, final int[] currentProfileIds) {
5603        synchronized (mWindowMap) {
5604            mCurrentUserId = newUserId;
5605            mCurrentProfileIds = currentProfileIds;
5606            mAppTransition.setCurrentUser(newUserId);
5607            mPolicy.setCurrentUserLw(newUserId);
5608
5609            // Hide windows that should not be seen by the new user.
5610            final int numDisplays = mDisplayContents.size();
5611            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5612                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
5613                displayContent.switchUserStacks(newUserId);
5614                rebuildAppWindowListLocked(displayContent);
5615            }
5616            performLayoutAndPlaceSurfacesLocked();
5617        }
5618    }
5619
5620    /* Called by WindowState */
5621    boolean isCurrentProfileLocked(int userId) {
5622        if (userId == mCurrentUserId) return true;
5623        for (int i = 0; i < mCurrentProfileIds.length; i++) {
5624            if (mCurrentProfileIds[i] == userId) return true;
5625        }
5626        return false;
5627    }
5628
5629    public void enableScreenAfterBoot() {
5630        synchronized(mWindowMap) {
5631            if (DEBUG_BOOT) {
5632                RuntimeException here = new RuntimeException("here");
5633                here.fillInStackTrace();
5634                Slog.i(TAG, "enableScreenAfterBoot: mDisplayEnabled=" + mDisplayEnabled
5635                        + " mForceDisplayEnabled=" + mForceDisplayEnabled
5636                        + " mShowingBootMessages=" + mShowingBootMessages
5637                        + " mSystemBooted=" + mSystemBooted, here);
5638            }
5639            if (mSystemBooted) {
5640                return;
5641            }
5642            mSystemBooted = true;
5643            hideBootMessagesLocked();
5644            // If the screen still doesn't come up after 30 seconds, give
5645            // up and turn it on.
5646            mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30*1000);
5647        }
5648
5649        mPolicy.systemBooted();
5650
5651        performEnableScreen();
5652    }
5653
5654    @Override
5655    public void enableScreenIfNeeded() {
5656        synchronized (mWindowMap) {
5657            enableScreenIfNeededLocked();
5658        }
5659    }
5660
5661    void enableScreenIfNeededLocked() {
5662        if (DEBUG_BOOT) {
5663            RuntimeException here = new RuntimeException("here");
5664            here.fillInStackTrace();
5665            Slog.i(TAG, "enableScreenIfNeededLocked: mDisplayEnabled=" + mDisplayEnabled
5666                    + " mForceDisplayEnabled=" + mForceDisplayEnabled
5667                    + " mShowingBootMessages=" + mShowingBootMessages
5668                    + " mSystemBooted=" + mSystemBooted, here);
5669        }
5670        if (mDisplayEnabled) {
5671            return;
5672        }
5673        if (!mSystemBooted && !mShowingBootMessages) {
5674            return;
5675        }
5676        mH.sendEmptyMessage(H.ENABLE_SCREEN);
5677    }
5678
5679    public void performBootTimeout() {
5680        synchronized(mWindowMap) {
5681            if (mDisplayEnabled) {
5682                return;
5683            }
5684            Slog.w(TAG, "***** BOOT TIMEOUT: forcing display enabled");
5685            mForceDisplayEnabled = true;
5686        }
5687        performEnableScreen();
5688    }
5689
5690    private boolean checkWaitingForWindowsLocked() {
5691
5692        boolean haveBootMsg = false;
5693        boolean haveApp = false;
5694        // if the wallpaper service is disabled on the device, we're never going to have
5695        // wallpaper, don't bother waiting for it
5696        boolean haveWallpaper = false;
5697        boolean wallpaperEnabled = mContext.getResources().getBoolean(
5698                com.android.internal.R.bool.config_enableWallpaperService)
5699                && !mOnlyCore;
5700        boolean haveKeyguard = true;
5701        // TODO(multidisplay): Expand to all displays?
5702        final WindowList windows = getDefaultWindowListLocked();
5703        final int N = windows.size();
5704        for (int i=0; i<N; i++) {
5705            WindowState w = windows.get(i);
5706            if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
5707                return true;
5708            }
5709            if (w.isDrawnLw()) {
5710                if (w.mAttrs.type == TYPE_BOOT_PROGRESS) {
5711                    haveBootMsg = true;
5712                } else if (w.mAttrs.type == TYPE_APPLICATION) {
5713                    haveApp = true;
5714                } else if (w.mAttrs.type == TYPE_WALLPAPER) {
5715                    haveWallpaper = true;
5716                } else if (w.mAttrs.type == TYPE_STATUS_BAR) {
5717                    haveKeyguard = mPolicy.isKeyguardDrawnLw();
5718                }
5719            }
5720        }
5721
5722        if (DEBUG_SCREEN_ON || DEBUG_BOOT) {
5723            Slog.i(TAG, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages
5724                    + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp
5725                    + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled
5726                    + " haveKeyguard=" + haveKeyguard);
5727        }
5728
5729        // If we are turning on the screen to show the boot message,
5730        // don't do it until the boot message is actually displayed.
5731        if (!mSystemBooted && !haveBootMsg) {
5732            return true;
5733        }
5734
5735        // If we are turning on the screen after the boot is completed
5736        // normally, don't do so until we have the application and
5737        // wallpaper.
5738        if (mSystemBooted && ((!haveApp && !haveKeyguard) ||
5739                (wallpaperEnabled && !haveWallpaper))) {
5740            return true;
5741        }
5742
5743        return false;
5744    }
5745
5746    public void performEnableScreen() {
5747        synchronized(mWindowMap) {
5748            if (DEBUG_BOOT) Slog.i(TAG, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled
5749                    + " mForceDisplayEnabled=" + mForceDisplayEnabled
5750                    + " mShowingBootMessages=" + mShowingBootMessages
5751                    + " mSystemBooted=" + mSystemBooted
5752                    + " mOnlyCore=" + mOnlyCore,
5753                    new RuntimeException("here").fillInStackTrace());
5754            if (mDisplayEnabled) {
5755                return;
5756            }
5757            if (!mSystemBooted && !mShowingBootMessages) {
5758                return;
5759            }
5760
5761            // Don't enable the screen until all existing windows have been drawn.
5762            if (!mForceDisplayEnabled && checkWaitingForWindowsLocked()) {
5763                return;
5764            }
5765
5766            if (!mBootAnimationStopped) {
5767                // Do this one time.
5768                try {
5769                    IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
5770                    if (surfaceFlinger != null) {
5771                        //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
5772                        Parcel data = Parcel.obtain();
5773                        data.writeInterfaceToken("android.ui.ISurfaceComposer");
5774                        surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
5775                                data, null, 0);
5776                        data.recycle();
5777                    }
5778                } catch (RemoteException ex) {
5779                    Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!");
5780                }
5781                mBootAnimationStopped = true;
5782            }
5783
5784            if (!mForceDisplayEnabled && !checkBootAnimationCompleteLocked()) {
5785                if (DEBUG_BOOT) Slog.i(TAG, "performEnableScreen: Waiting for anim complete");
5786                return;
5787            }
5788
5789            mDisplayEnabled = true;
5790            if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG, "******************** ENABLING SCREEN!");
5791
5792            // Enable input dispatch.
5793            mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled);
5794        }
5795
5796        try {
5797            mActivityManager.bootAnimationComplete();
5798        } catch (RemoteException e) {
5799        }
5800
5801        mPolicy.enableScreenAfterBoot();
5802
5803        // Make sure the last requested orientation has been applied.
5804        updateRotationUnchecked(false, false);
5805    }
5806
5807    private boolean checkBootAnimationCompleteLocked() {
5808        if (SystemService.isRunning(BOOT_ANIMATION_SERVICE)) {
5809            mH.removeMessages(H.CHECK_IF_BOOT_ANIMATION_FINISHED);
5810            mH.sendEmptyMessageDelayed(H.CHECK_IF_BOOT_ANIMATION_FINISHED,
5811                    BOOT_ANIMATION_POLL_INTERVAL);
5812            if (DEBUG_BOOT) Slog.i(TAG, "checkBootAnimationComplete: Waiting for anim complete");
5813            return false;
5814        }
5815        if (DEBUG_BOOT) Slog.i(TAG, "checkBootAnimationComplete: Animation complete!");
5816        return true;
5817    }
5818
5819    public void showBootMessage(final CharSequence msg, final boolean always) {
5820        boolean first = false;
5821        synchronized(mWindowMap) {
5822            if (DEBUG_BOOT) {
5823                RuntimeException here = new RuntimeException("here");
5824                here.fillInStackTrace();
5825                Slog.i(TAG, "showBootMessage: msg=" + msg + " always=" + always
5826                        + " mAllowBootMessages=" + mAllowBootMessages
5827                        + " mShowingBootMessages=" + mShowingBootMessages
5828                        + " mSystemBooted=" + mSystemBooted, here);
5829            }
5830            if (!mAllowBootMessages) {
5831                return;
5832            }
5833            if (!mShowingBootMessages) {
5834                if (!always) {
5835                    return;
5836                }
5837                first = true;
5838            }
5839            if (mSystemBooted) {
5840                return;
5841            }
5842            mShowingBootMessages = true;
5843            mPolicy.showBootMessage(msg, always);
5844        }
5845        if (first) {
5846            performEnableScreen();
5847        }
5848    }
5849
5850    public void hideBootMessagesLocked() {
5851        if (DEBUG_BOOT) {
5852            RuntimeException here = new RuntimeException("here");
5853            here.fillInStackTrace();
5854            Slog.i(TAG, "hideBootMessagesLocked: mDisplayEnabled=" + mDisplayEnabled
5855                    + " mForceDisplayEnabled=" + mForceDisplayEnabled
5856                    + " mShowingBootMessages=" + mShowingBootMessages
5857                    + " mSystemBooted=" + mSystemBooted, here);
5858        }
5859        if (mShowingBootMessages) {
5860            mShowingBootMessages = false;
5861            mPolicy.hideBootMessages();
5862        }
5863    }
5864
5865    @Override
5866    public void setInTouchMode(boolean mode) {
5867        synchronized(mWindowMap) {
5868            mInTouchMode = mode;
5869        }
5870    }
5871
5872    public void updateCircularDisplayMaskIfNeeded() {
5873        // we're fullscreen and not hosted in an ActivityView
5874        if (mContext.getResources().getBoolean(
5875                com.android.internal.R.bool.config_windowIsRound)
5876                && mContext.getResources().getBoolean(
5877                com.android.internal.R.bool.config_windowShowCircularMask)) {
5878            // Device configuration calls for a circular display mask, but we only enable the mask
5879            // if the accessibility color inversion feature is disabled, as the inverted mask
5880            // causes artifacts.
5881            int inversionState = Settings.Secure.getIntForUser(mContext.getContentResolver(),
5882                    Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, mCurrentUserId);
5883            int showMask = (inversionState == 1) ? 0 : 1;
5884            Message m = mH.obtainMessage(H.SHOW_CIRCULAR_DISPLAY_MASK);
5885            m.arg1 = showMask;
5886            mH.sendMessage(m);
5887        }
5888    }
5889
5890    public void showEmulatorDisplayOverlayIfNeeded() {
5891        if (mContext.getResources().getBoolean(
5892                com.android.internal.R.bool.config_windowEnableCircularEmulatorDisplayOverlay)
5893                && SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false)
5894                && Build.HARDWARE.contains("goldfish")) {
5895            mH.sendMessage(mH.obtainMessage(H.SHOW_EMULATOR_DISPLAY_OVERLAY));
5896        }
5897    }
5898
5899    public void showCircularMask(boolean visible) {
5900        synchronized(mWindowMap) {
5901
5902            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5903                    ">>> OPEN TRANSACTION showCircularMask(visible=" + visible + ")");
5904            SurfaceControl.openTransaction();
5905            try {
5906                if (visible) {
5907                    // TODO(multi-display): support multiple displays
5908                    if (mCircularDisplayMask == null) {
5909                        int screenOffset = mContext.getResources().getDimensionPixelSize(
5910                                com.android.internal.R.dimen.circular_display_mask_offset);
5911
5912                        mCircularDisplayMask = new CircularDisplayMask(
5913                                getDefaultDisplayContentLocked().getDisplay(),
5914                                mFxSession,
5915                                mPolicy.windowTypeToLayerLw(
5916                                        WindowManager.LayoutParams.TYPE_POINTER)
5917                                        * TYPE_LAYER_MULTIPLIER + 10, screenOffset);
5918                    }
5919                    mCircularDisplayMask.setVisibility(true);
5920                } else if (mCircularDisplayMask != null) {
5921                    mCircularDisplayMask.setVisibility(false);
5922                    mCircularDisplayMask = null;
5923                }
5924            } finally {
5925                SurfaceControl.closeTransaction();
5926                if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5927                        "<<< CLOSE TRANSACTION showCircularMask(visible=" + visible + ")");
5928            }
5929        }
5930    }
5931
5932    public void showEmulatorDisplayOverlay() {
5933        synchronized(mWindowMap) {
5934
5935            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5936                    ">>> OPEN TRANSACTION showEmulatorDisplayOverlay");
5937            SurfaceControl.openTransaction();
5938            try {
5939                if (mEmulatorDisplayOverlay == null) {
5940                    mEmulatorDisplayOverlay = new EmulatorDisplayOverlay(
5941                            mContext,
5942                            getDefaultDisplayContentLocked().getDisplay(),
5943                            mFxSession,
5944                            mPolicy.windowTypeToLayerLw(
5945                                    WindowManager.LayoutParams.TYPE_POINTER)
5946                                    * TYPE_LAYER_MULTIPLIER + 10);
5947                }
5948                mEmulatorDisplayOverlay.setVisibility(true);
5949            } finally {
5950                SurfaceControl.closeTransaction();
5951                if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5952                        "<<< CLOSE TRANSACTION showEmulatorDisplayOverlay");
5953            }
5954        }
5955    }
5956
5957    // TODO: more accounting of which pid(s) turned it on, keep count,
5958    // only allow disables from pids which have count on, etc.
5959    @Override
5960    public void showStrictModeViolation(boolean on) {
5961        int pid = Binder.getCallingPid();
5962        mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, pid));
5963    }
5964
5965    private void showStrictModeViolation(int arg, int pid) {
5966        final boolean on = arg != 0;
5967        synchronized(mWindowMap) {
5968            // Ignoring requests to enable the red border from clients
5969            // which aren't on screen.  (e.g. Broadcast Receivers in
5970            // the background..)
5971            if (on) {
5972                boolean isVisible = false;
5973                final int numDisplays = mDisplayContents.size();
5974                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5975                    final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
5976                    final int numWindows = windows.size();
5977                    for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
5978                        final WindowState ws = windows.get(winNdx);
5979                        if (ws.mSession.mPid == pid && ws.isVisibleLw()) {
5980                            isVisible = true;
5981                            break;
5982                        }
5983                    }
5984                }
5985                if (!isVisible) {
5986                    return;
5987                }
5988            }
5989
5990            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5991                    ">>> OPEN TRANSACTION showStrictModeViolation");
5992            SurfaceControl.openTransaction();
5993            try {
5994                // TODO(multi-display): support multiple displays
5995                if (mStrictModeFlash == null) {
5996                    mStrictModeFlash = new StrictModeFlash(
5997                            getDefaultDisplayContentLocked().getDisplay(), mFxSession);
5998                }
5999                mStrictModeFlash.setVisibility(on);
6000            } finally {
6001                SurfaceControl.closeTransaction();
6002                if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
6003                        "<<< CLOSE TRANSACTION showStrictModeViolation");
6004            }
6005        }
6006    }
6007
6008    @Override
6009    public void setStrictModeVisualIndicatorPreference(String value) {
6010        SystemProperties.set(StrictMode.VISUAL_PROPERTY, value);
6011    }
6012
6013    private static void convertCropForSurfaceFlinger(Rect crop, int rot, int dw, int dh) {
6014        if (rot == Surface.ROTATION_90) {
6015            final int tmp = crop.top;
6016            crop.top = dw - crop.right;
6017            crop.right = crop.bottom;
6018            crop.bottom = dw - crop.left;
6019            crop.left = tmp;
6020        } else if (rot == Surface.ROTATION_180) {
6021            int tmp = crop.top;
6022            crop.top = dh - crop.bottom;
6023            crop.bottom = dh - tmp;
6024            tmp = crop.right;
6025            crop.right = dw - crop.left;
6026            crop.left = dw - tmp;
6027        } else if (rot == Surface.ROTATION_270) {
6028            final int tmp = crop.top;
6029            crop.top = crop.left;
6030            crop.left = dh - crop.bottom;
6031            crop.bottom = crop.right;
6032            crop.right = dh - tmp;
6033        }
6034    }
6035
6036    /**
6037     * Takes a snapshot of the screen.  In landscape mode this grabs the whole screen.
6038     * In portrait mode, it grabs the upper region of the screen based on the vertical dimension
6039     * of the target image.
6040     *
6041     * @param displayId the Display to take a screenshot of.
6042     * @param width the width of the target bitmap
6043     * @param height the height of the target bitmap
6044     * @param force565 if true the returned bitmap will be RGB_565, otherwise it
6045     *                 will be the same config as the surface
6046     */
6047    @Override
6048    public Bitmap screenshotApplications(IBinder appToken, int displayId, int width,
6049            int height, boolean force565) {
6050        if (!checkCallingPermission(Manifest.permission.READ_FRAME_BUFFER,
6051                "screenshotApplications()")) {
6052            throw new SecurityException("Requires READ_FRAME_BUFFER permission");
6053        }
6054
6055        final DisplayContent displayContent = getDisplayContentLocked(displayId);
6056        if (displayContent == null) {
6057            if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken
6058                    + ": returning null. No Display for displayId=" + displayId);
6059            return null;
6060        }
6061        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
6062        int dw = displayInfo.logicalWidth;
6063        int dh = displayInfo.logicalHeight;
6064        if (dw == 0 || dh == 0) {
6065            if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken
6066                    + ": returning null. logical widthxheight=" + dw + "x" + dh);
6067            return null;
6068        }
6069
6070        Bitmap bm = null;
6071
6072        int maxLayer = 0;
6073        final Rect frame = new Rect();
6074        final Rect stackBounds = new Rect();
6075
6076        float scale = 0;
6077        int rot = Surface.ROTATION_0;
6078
6079        boolean screenshotReady;
6080        int minLayer;
6081        if (appToken == null) {
6082            screenshotReady = true;
6083            minLayer = 0;
6084        } else {
6085            screenshotReady = false;
6086            minLayer = Integer.MAX_VALUE;
6087        }
6088
6089        int retryCount = 0;
6090        WindowState appWin = null;
6091
6092        final boolean appIsImTarget = mInputMethodTarget != null
6093                && mInputMethodTarget.mAppToken != null
6094                && mInputMethodTarget.mAppToken.appToken != null
6095                && mInputMethodTarget.mAppToken.appToken.asBinder() == appToken;
6096
6097        final int aboveAppLayer = (mPolicy.windowTypeToLayerLw(TYPE_APPLICATION) + 1)
6098                * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
6099
6100        while (true) {
6101            if (retryCount++ > 0) {
6102                // Reset max/min layers on retries so we don't accidentally take a screenshot of a
6103                // layer based on the previous try.
6104                maxLayer = 0;
6105                minLayer = Integer.MAX_VALUE;
6106                try {
6107                    Thread.sleep(100);
6108                } catch (InterruptedException e) {
6109                }
6110            }
6111            synchronized(mWindowMap) {
6112                // Figure out the part of the screen that is actually the app.
6113                appWin = null;
6114                final WindowList windows = displayContent.getWindowList();
6115                for (int i = windows.size() - 1; i >= 0; i--) {
6116                    WindowState ws = windows.get(i);
6117                    if (!ws.mHasSurface) {
6118                        continue;
6119                    }
6120                    if (ws.mLayer >= aboveAppLayer) {
6121                        continue;
6122                    }
6123                    if (ws.mIsImWindow) {
6124                        if (!appIsImTarget) {
6125                            continue;
6126                        }
6127                    } else if (ws.mIsWallpaper) {
6128                        if (appWin == null) {
6129                            // We have not ran across the target window yet, so it is probably
6130                            // behind the wallpaper. This can happen when the keyguard is up and
6131                            // all windows are moved behind the wallpaper. We don't want to
6132                            // include the wallpaper layer in the screenshot as it will coverup
6133                            // the layer of the target window.
6134                            continue;
6135                        }
6136                        // Fall through. The target window is in front of the wallpaper. For this
6137                        // case we want to include the wallpaper layer in the screenshot because
6138                        // the target window might have some transparent areas.
6139                    } else if (appToken != null) {
6140                        if (ws.mAppToken == null || ws.mAppToken.token != appToken) {
6141                            // This app window is of no interest if it is not associated with the
6142                            // screenshot app.
6143                            continue;
6144                        }
6145                        appWin = ws;
6146                    }
6147
6148                    // Include this window.
6149
6150                    final WindowStateAnimator winAnim = ws.mWinAnimator;
6151                    if (maxLayer < winAnim.mSurfaceLayer) {
6152                        maxLayer = winAnim.mSurfaceLayer;
6153                    }
6154                    if (minLayer > winAnim.mSurfaceLayer) {
6155                        minLayer = winAnim.mSurfaceLayer;
6156                    }
6157
6158                    // Don't include wallpaper in bounds calculation
6159                    if (!ws.mIsWallpaper) {
6160                        final Rect wf = ws.mFrame;
6161                        final Rect cr = ws.mContentInsets;
6162                        int left = wf.left + cr.left;
6163                        int top = wf.top + cr.top;
6164                        int right = wf.right - cr.right;
6165                        int bottom = wf.bottom - cr.bottom;
6166                        frame.union(left, top, right, bottom);
6167                        ws.getStackBounds(stackBounds);
6168                        frame.intersect(stackBounds);
6169                    }
6170
6171                    if (ws.mAppToken != null && ws.mAppToken.token == appToken &&
6172                            ws.isDisplayedLw()) {
6173                        screenshotReady = true;
6174                    }
6175                }
6176
6177                if (appToken != null && appWin == null) {
6178                    // Can't find a window to snapshot.
6179                    if (DEBUG_SCREENSHOT) Slog.i(TAG,
6180                            "Screenshot: Couldn't find a surface matching " + appToken);
6181                    return null;
6182                }
6183
6184                if (!screenshotReady) {
6185                    if (retryCount > MAX_SCREENSHOT_RETRIES) {
6186                        Slog.i(TAG, "Screenshot max retries " + retryCount + " of " + appToken +
6187                                " appWin=" + (appWin == null ? "null" : (appWin + " drawState=" +
6188                                appWin.mWinAnimator.mDrawState)));
6189                        return null;
6190                    }
6191
6192                    // Delay and hope that window gets drawn.
6193                    if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot: No image ready for " + appToken
6194                            + ", " + appWin + " drawState=" + appWin.mWinAnimator.mDrawState);
6195                    continue;
6196                }
6197
6198                // Screenshot is ready to be taken. Everything from here below will continue
6199                // through the bottom of the loop and return a value. We only stay in the loop
6200                // because we don't want to release the mWindowMap lock until the screenshot is
6201                // taken.
6202
6203                if (maxLayer == 0) {
6204                    if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken
6205                            + ": returning null maxLayer=" + maxLayer);
6206                    return null;
6207                }
6208
6209                // Constrain frame to the screen size.
6210                frame.intersect(0, 0, dw, dh);
6211
6212                // Tell surface flinger what part of the image to crop. Take the top
6213                // right part of the application, and crop the larger dimension to fit.
6214                Rect crop = new Rect(frame);
6215                if (width / (float) frame.width() < height / (float) frame.height()) {
6216                    int cropWidth = (int)((float)width / (float)height * frame.height());
6217                    crop.right = crop.left + cropWidth;
6218                } else {
6219                    int cropHeight = (int)((float)height / (float)width * frame.width());
6220                    crop.bottom = crop.top + cropHeight;
6221                }
6222
6223                // The screenshot API does not apply the current screen rotation.
6224                rot = getDefaultDisplayContentLocked().getDisplay().getRotation();
6225
6226                if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
6227                    rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90;
6228                }
6229
6230                // Surfaceflinger is not aware of orientation, so convert our logical
6231                // crop to surfaceflinger's portrait orientation.
6232                convertCropForSurfaceFlinger(crop, rot, dw, dh);
6233
6234                if (DEBUG_SCREENSHOT) {
6235                    Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to "
6236                            + maxLayer + " appToken=" + appToken);
6237                    for (int i = 0; i < windows.size(); i++) {
6238                        WindowState win = windows.get(i);
6239                        Slog.i(TAG, win + ": " + win.mLayer
6240                                + " animLayer=" + win.mWinAnimator.mAnimLayer
6241                                + " surfaceLayer=" + win.mWinAnimator.mSurfaceLayer);
6242                    }
6243                }
6244
6245                ScreenRotationAnimation screenRotationAnimation =
6246                        mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
6247                final boolean inRotation = screenRotationAnimation != null &&
6248                        screenRotationAnimation.isAnimating();
6249                if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG,
6250                        "Taking screenshot while rotating");
6251
6252                bm = SurfaceControl.screenshot(crop, width, height, minLayer, maxLayer,
6253                        inRotation, rot);
6254                if (bm == null) {
6255                    Slog.w(TAG, "Screenshot failure taking screenshot for (" + dw + "x" + dh
6256                            + ") to layer " + maxLayer);
6257                    return null;
6258                }
6259            }
6260
6261            break;
6262        }
6263
6264        if (DEBUG_SCREENSHOT) {
6265            // TEST IF IT's ALL BLACK
6266            int[] buffer = new int[bm.getWidth() * bm.getHeight()];
6267            bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight());
6268            boolean allBlack = true;
6269            final int firstColor = buffer[0];
6270            for (int i = 0; i < buffer.length; i++) {
6271                if (buffer[i] != firstColor) {
6272                    allBlack = false;
6273                    break;
6274                }
6275            }
6276            if (allBlack) {
6277                Slog.i(TAG, "Screenshot " + appWin + " was monochrome(" +
6278                        Integer.toHexString(firstColor) + ")! mSurfaceLayer=" +
6279                        (appWin != null ? appWin.mWinAnimator.mSurfaceLayer : "null") +
6280                        " minLayer=" + minLayer + " maxLayer=" + maxLayer);
6281            }
6282        }
6283
6284        // Copy the screenshot bitmap to another buffer so that the gralloc backed
6285        // bitmap will not have a long lifetime. Gralloc memory can be pinned or
6286        // duplicated and might have a higher cost than a skia backed buffer.
6287        Bitmap ret = bm.copy(bm.getConfig(),true);
6288        bm.recycle();
6289        return ret;
6290    }
6291
6292    /**
6293     * Freeze rotation changes.  (Enable "rotation lock".)
6294     * Persists across reboots.
6295     * @param rotation The desired rotation to freeze to, or -1 to use the
6296     * current rotation.
6297     */
6298    @Override
6299    public void freezeRotation(int rotation) {
6300        if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
6301                "freezeRotation()")) {
6302            throw new SecurityException("Requires SET_ORIENTATION permission");
6303        }
6304        if (rotation < -1 || rotation > Surface.ROTATION_270) {
6305            throw new IllegalArgumentException("Rotation argument must be -1 or a valid "
6306                    + "rotation constant.");
6307        }
6308
6309        if (DEBUG_ORIENTATION) Slog.v(TAG, "freezeRotation: mRotation=" + mRotation);
6310
6311        long origId = Binder.clearCallingIdentity();
6312        try {
6313            mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED,
6314                    rotation == -1 ? mRotation : rotation);
6315        } finally {
6316            Binder.restoreCallingIdentity(origId);
6317        }
6318
6319        updateRotationUnchecked(false, false);
6320    }
6321
6322    /**
6323     * Thaw rotation changes.  (Disable "rotation lock".)
6324     * Persists across reboots.
6325     */
6326    @Override
6327    public void thawRotation() {
6328        if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
6329                "thawRotation()")) {
6330            throw new SecurityException("Requires SET_ORIENTATION permission");
6331        }
6332
6333        if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation);
6334
6335        long origId = Binder.clearCallingIdentity();
6336        try {
6337            mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE,
6338                    777); // rot not used
6339        } finally {
6340            Binder.restoreCallingIdentity(origId);
6341        }
6342
6343        updateRotationUnchecked(false, false);
6344    }
6345
6346    /**
6347     * Recalculate the current rotation.
6348     *
6349     * Called by the window manager policy whenever the state of the system changes
6350     * such that the current rotation might need to be updated, such as when the
6351     * device is docked or rotated into a new posture.
6352     */
6353    @Override
6354    public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
6355        updateRotationUnchecked(alwaysSendConfiguration, forceRelayout);
6356    }
6357
6358    /**
6359     * Temporarily pauses rotation changes until resumed.
6360     *
6361     * This can be used to prevent rotation changes from occurring while the user is
6362     * performing certain operations, such as drag and drop.
6363     *
6364     * This call nests and must be matched by an equal number of calls to
6365     * {@link #resumeRotationLocked}.
6366     */
6367    void pauseRotationLocked() {
6368        mDeferredRotationPauseCount += 1;
6369    }
6370
6371    /**
6372     * Resumes normal rotation changes after being paused.
6373     */
6374    void resumeRotationLocked() {
6375        if (mDeferredRotationPauseCount > 0) {
6376            mDeferredRotationPauseCount -= 1;
6377            if (mDeferredRotationPauseCount == 0) {
6378                boolean changed = updateRotationUncheckedLocked(false);
6379                if (changed) {
6380                    mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
6381                }
6382            }
6383        }
6384    }
6385
6386    public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) {
6387        if(DEBUG_ORIENTATION) Slog.v(TAG, "updateRotationUnchecked("
6388                   + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")");
6389
6390        long origId = Binder.clearCallingIdentity();
6391        boolean changed;
6392        synchronized(mWindowMap) {
6393            changed = updateRotationUncheckedLocked(false);
6394            if (!changed || forceRelayout) {
6395                getDefaultDisplayContentLocked().layoutNeeded = true;
6396                performLayoutAndPlaceSurfacesLocked();
6397            }
6398        }
6399
6400        if (changed || alwaysSendConfiguration) {
6401            sendNewConfiguration();
6402        }
6403
6404        Binder.restoreCallingIdentity(origId);
6405    }
6406
6407    // TODO(multidisplay): Rotate any display?
6408    /**
6409     * Updates the current rotation.
6410     *
6411     * Returns true if the rotation has been changed.  In this case YOU
6412     * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN.
6413     */
6414    public boolean updateRotationUncheckedLocked(boolean inTransaction) {
6415        if (mDeferredRotationPauseCount > 0) {
6416            // Rotation updates have been paused temporarily.  Defer the update until
6417            // updates have been resumed.
6418            if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, rotation is paused.");
6419            return false;
6420        }
6421
6422        ScreenRotationAnimation screenRotationAnimation =
6423                mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
6424        if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
6425            // Rotation updates cannot be performed while the previous rotation change
6426            // animation is still in progress.  Skip this update.  We will try updating
6427            // again after the animation is finished and the display is unfrozen.
6428            if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, animation in progress.");
6429            return false;
6430        }
6431
6432        if (!mDisplayEnabled) {
6433            // No point choosing a rotation if the display is not enabled.
6434            if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, display is not enabled.");
6435            return false;
6436        }
6437
6438        // TODO: Implement forced rotation changes.
6439        //       Set mAltOrientation to indicate that the application is receiving
6440        //       an orientation that has different metrics than it expected.
6441        //       eg. Portrait instead of Landscape.
6442
6443        int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation);
6444        boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw(
6445                mForcedAppOrientation, rotation);
6446
6447        if (DEBUG_ORIENTATION) {
6448            Slog.v(TAG, "Application requested orientation "
6449                    + mForcedAppOrientation + ", got rotation " + rotation
6450                    + " which has " + (altOrientation ? "incompatible" : "compatible")
6451                    + " metrics");
6452        }
6453
6454        if (mRotation == rotation && mAltOrientation == altOrientation) {
6455            // No change.
6456            return false;
6457        }
6458
6459        if (DEBUG_ORIENTATION) {
6460            Slog.v(TAG,
6461                "Rotation changed to " + rotation + (altOrientation ? " (alt)" : "")
6462                + " from " + mRotation + (mAltOrientation ? " (alt)" : "")
6463                + ", forceApp=" + mForcedAppOrientation);
6464        }
6465
6466        mRotation = rotation;
6467        mAltOrientation = altOrientation;
6468        mPolicy.setRotationLw(mRotation);
6469
6470        mWindowsFreezingScreen = true;
6471        mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
6472        mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION);
6473        mWaitingForConfig = true;
6474        final DisplayContent displayContent = getDefaultDisplayContentLocked();
6475        displayContent.layoutNeeded = true;
6476        final int[] anim = new int[2];
6477        if (displayContent.isDimming()) {
6478            anim[0] = anim[1] = 0;
6479        } else {
6480            mPolicy.selectRotationAnimationLw(anim);
6481        }
6482        startFreezingDisplayLocked(inTransaction, anim[0], anim[1]);
6483        // startFreezingDisplayLocked can reset the ScreenRotationAnimation.
6484        screenRotationAnimation =
6485                mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
6486
6487        // We need to update our screen size information to match the new
6488        // rotation.  Note that this is redundant with the later call to
6489        // sendNewConfiguration() that must be called after this function
6490        // returns...  however we need to do the screen size part of that
6491        // before then so we have the correct size to use when initializing
6492        // the rotation animation for the new rotation.
6493        computeScreenConfigurationLocked(null);
6494
6495        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
6496        if (!inTransaction) {
6497            if (SHOW_TRANSACTIONS) {
6498                Slog.i(TAG, ">>> OPEN TRANSACTION setRotationUnchecked");
6499            }
6500            SurfaceControl.openTransaction();
6501        }
6502        try {
6503            // NOTE: We disable the rotation in the emulator because
6504            //       it doesn't support hardware OpenGL emulation yet.
6505            if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
6506                    && screenRotationAnimation.hasScreenshot()) {
6507                if (screenRotationAnimation.setRotationInTransaction(
6508                        rotation, mFxSession,
6509                        MAX_ANIMATION_DURATION, getTransitionAnimationScaleLocked(),
6510                        displayInfo.logicalWidth, displayInfo.logicalHeight)) {
6511                    scheduleAnimationLocked();
6512                }
6513            }
6514
6515            mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
6516        } finally {
6517            if (!inTransaction) {
6518                SurfaceControl.closeTransaction();
6519                if (SHOW_LIGHT_TRANSACTIONS) {
6520                    Slog.i(TAG, "<<< CLOSE TRANSACTION setRotationUnchecked");
6521                }
6522            }
6523        }
6524
6525        final WindowList windows = displayContent.getWindowList();
6526        for (int i = windows.size() - 1; i >= 0; i--) {
6527            WindowState w = windows.get(i);
6528            if (w.mHasSurface) {
6529                if (DEBUG_ORIENTATION) Slog.v(TAG, "Set mOrientationChanging of " + w);
6530                w.mOrientationChanging = true;
6531                mInnerFields.mOrientationChangeComplete = false;
6532            }
6533            w.mLastFreezeDuration = 0;
6534        }
6535
6536        for (int i=mRotationWatchers.size()-1; i>=0; i--) {
6537            try {
6538                mRotationWatchers.get(i).watcher.onRotationChanged(rotation);
6539            } catch (RemoteException e) {
6540            }
6541        }
6542
6543        //TODO (multidisplay): Magnification is supported only for the default display.
6544        // Announce rotation only if we will not animate as we already have the
6545        // windows in final state. Otherwise, we make this call at the rotation end.
6546        if (screenRotationAnimation == null && mAccessibilityController != null
6547                && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) {
6548            mAccessibilityController.onRotationChangedLocked(getDefaultDisplayContentLocked(),
6549                    rotation);
6550        }
6551
6552        return true;
6553    }
6554
6555    @Override
6556    public int getRotation() {
6557        return mRotation;
6558    }
6559
6560    @Override
6561    public boolean isRotationFrozen() {
6562        return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED;
6563    }
6564
6565    @Override
6566    public int watchRotation(IRotationWatcher watcher) {
6567        final IBinder watcherBinder = watcher.asBinder();
6568        IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
6569            @Override
6570            public void binderDied() {
6571                synchronized (mWindowMap) {
6572                    for (int i=0; i<mRotationWatchers.size(); i++) {
6573                        if (watcherBinder == mRotationWatchers.get(i).watcher.asBinder()) {
6574                            RotationWatcher removed = mRotationWatchers.remove(i);
6575                            IBinder binder = removed.watcher.asBinder();
6576                            if (binder != null) {
6577                                binder.unlinkToDeath(this, 0);
6578                            }
6579                            i--;
6580                        }
6581                    }
6582                }
6583            }
6584        };
6585
6586        synchronized (mWindowMap) {
6587            try {
6588                watcher.asBinder().linkToDeath(dr, 0);
6589                mRotationWatchers.add(new RotationWatcher(watcher, dr));
6590            } catch (RemoteException e) {
6591                // Client died, no cleanup needed.
6592            }
6593
6594            return mRotation;
6595        }
6596    }
6597
6598    @Override
6599    public void removeRotationWatcher(IRotationWatcher watcher) {
6600        final IBinder watcherBinder = watcher.asBinder();
6601        synchronized (mWindowMap) {
6602            for (int i=0; i<mRotationWatchers.size(); i++) {
6603                RotationWatcher rotationWatcher = mRotationWatchers.get(i);
6604                if (watcherBinder == rotationWatcher.watcher.asBinder()) {
6605                    RotationWatcher removed = mRotationWatchers.remove(i);
6606                    IBinder binder = removed.watcher.asBinder();
6607                    if (binder != null) {
6608                        binder.unlinkToDeath(removed.deathRecipient, 0);
6609                    }
6610                    i--;
6611                }
6612            }
6613        }
6614    }
6615
6616    /**
6617     * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact
6618     * theme attribute) on devices that feature a physical options menu key attempt to position
6619     * their menu panel window along the edge of the screen nearest the physical menu key.
6620     * This lowers the travel distance between invoking the menu panel and selecting
6621     * a menu option.
6622     *
6623     * This method helps control where that menu is placed. Its current implementation makes
6624     * assumptions about the menu key and its relationship to the screen based on whether
6625     * the device's natural orientation is portrait (width < height) or landscape.
6626     *
6627     * The menu key is assumed to be located along the bottom edge of natural-portrait
6628     * devices and along the right edge of natural-landscape devices. If these assumptions
6629     * do not hold for the target device, this method should be changed to reflect that.
6630     *
6631     * @return A {@link Gravity} value for placing the options menu window
6632     */
6633    @Override
6634    public int getPreferredOptionsPanelGravity() {
6635        synchronized (mWindowMap) {
6636            final int rotation = getRotation();
6637
6638            // TODO(multidisplay): Assume that such devices physical keys are on the main screen.
6639            final DisplayContent displayContent = getDefaultDisplayContentLocked();
6640            if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) {
6641                // On devices with a natural orientation of portrait
6642                switch (rotation) {
6643                    default:
6644                    case Surface.ROTATION_0:
6645                        return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6646                    case Surface.ROTATION_90:
6647                        return Gravity.RIGHT | Gravity.BOTTOM;
6648                    case Surface.ROTATION_180:
6649                        return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6650                    case Surface.ROTATION_270:
6651                        return Gravity.START | Gravity.BOTTOM;
6652                }
6653            }
6654
6655            // On devices with a natural orientation of landscape
6656            switch (rotation) {
6657                default:
6658                case Surface.ROTATION_0:
6659                    return Gravity.RIGHT | Gravity.BOTTOM;
6660                case Surface.ROTATION_90:
6661                    return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6662                case Surface.ROTATION_180:
6663                    return Gravity.START | Gravity.BOTTOM;
6664                case Surface.ROTATION_270:
6665                    return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6666            }
6667        }
6668    }
6669
6670    /**
6671     * Starts the view server on the specified port.
6672     *
6673     * @param port The port to listener to.
6674     *
6675     * @return True if the server was successfully started, false otherwise.
6676     *
6677     * @see com.android.server.wm.ViewServer
6678     * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT
6679     */
6680    @Override
6681    public boolean startViewServer(int port) {
6682        if (isSystemSecure()) {
6683            return false;
6684        }
6685
6686        if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) {
6687            return false;
6688        }
6689
6690        if (port < 1024) {
6691            return false;
6692        }
6693
6694        if (mViewServer != null) {
6695            if (!mViewServer.isRunning()) {
6696                try {
6697                    return mViewServer.start();
6698                } catch (IOException e) {
6699                    Slog.w(TAG, "View server did not start");
6700                }
6701            }
6702            return false;
6703        }
6704
6705        try {
6706            mViewServer = new ViewServer(this, port);
6707            return mViewServer.start();
6708        } catch (IOException e) {
6709            Slog.w(TAG, "View server did not start");
6710        }
6711        return false;
6712    }
6713
6714    private boolean isSystemSecure() {
6715        return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) &&
6716                "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
6717    }
6718
6719    /**
6720     * Stops the view server if it exists.
6721     *
6722     * @return True if the server stopped, false if it wasn't started or
6723     *         couldn't be stopped.
6724     *
6725     * @see com.android.server.wm.ViewServer
6726     */
6727    @Override
6728    public boolean stopViewServer() {
6729        if (isSystemSecure()) {
6730            return false;
6731        }
6732
6733        if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) {
6734            return false;
6735        }
6736
6737        if (mViewServer != null) {
6738            return mViewServer.stop();
6739        }
6740        return false;
6741    }
6742
6743    /**
6744     * Indicates whether the view server is running.
6745     *
6746     * @return True if the server is running, false otherwise.
6747     *
6748     * @see com.android.server.wm.ViewServer
6749     */
6750    @Override
6751    public boolean isViewServerRunning() {
6752        if (isSystemSecure()) {
6753            return false;
6754        }
6755
6756        if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) {
6757            return false;
6758        }
6759
6760        return mViewServer != null && mViewServer.isRunning();
6761    }
6762
6763    /**
6764     * Lists all availble windows in the system. The listing is written in the
6765     * specified Socket's output stream with the following syntax:
6766     * windowHashCodeInHexadecimal windowName
6767     * Each line of the ouput represents a different window.
6768     *
6769     * @param client The remote client to send the listing to.
6770     * @return False if an error occured, true otherwise.
6771     */
6772    boolean viewServerListWindows(Socket client) {
6773        if (isSystemSecure()) {
6774            return false;
6775        }
6776
6777        boolean result = true;
6778
6779        WindowList windows = new WindowList();
6780        synchronized (mWindowMap) {
6781            //noinspection unchecked
6782            final int numDisplays = mDisplayContents.size();
6783            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
6784                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
6785                windows.addAll(displayContent.getWindowList());
6786            }
6787        }
6788
6789        BufferedWriter out = null;
6790
6791        // Any uncaught exception will crash the system process
6792        try {
6793            OutputStream clientStream = client.getOutputStream();
6794            out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
6795
6796            final int count = windows.size();
6797            for (int i = 0; i < count; i++) {
6798                final WindowState w = windows.get(i);
6799                out.write(Integer.toHexString(System.identityHashCode(w)));
6800                out.write(' ');
6801                out.append(w.mAttrs.getTitle());
6802                out.write('\n');
6803            }
6804
6805            out.write("DONE.\n");
6806            out.flush();
6807        } catch (Exception e) {
6808            result = false;
6809        } finally {
6810            if (out != null) {
6811                try {
6812                    out.close();
6813                } catch (IOException e) {
6814                    result = false;
6815                }
6816            }
6817        }
6818
6819        return result;
6820    }
6821
6822    // TODO(multidisplay): Extend to multiple displays.
6823    /**
6824     * Returns the focused window in the following format:
6825     * windowHashCodeInHexadecimal windowName
6826     *
6827     * @param client The remote client to send the listing to.
6828     * @return False if an error occurred, true otherwise.
6829     */
6830    boolean viewServerGetFocusedWindow(Socket client) {
6831        if (isSystemSecure()) {
6832            return false;
6833        }
6834
6835        boolean result = true;
6836
6837        WindowState focusedWindow = getFocusedWindow();
6838
6839        BufferedWriter out = null;
6840
6841        // Any uncaught exception will crash the system process
6842        try {
6843            OutputStream clientStream = client.getOutputStream();
6844            out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
6845
6846            if(focusedWindow != null) {
6847                out.write(Integer.toHexString(System.identityHashCode(focusedWindow)));
6848                out.write(' ');
6849                out.append(focusedWindow.mAttrs.getTitle());
6850            }
6851            out.write('\n');
6852            out.flush();
6853        } catch (Exception e) {
6854            result = false;
6855        } finally {
6856            if (out != null) {
6857                try {
6858                    out.close();
6859                } catch (IOException e) {
6860                    result = false;
6861                }
6862            }
6863        }
6864
6865        return result;
6866    }
6867
6868    /**
6869     * Sends a command to a target window. The result of the command, if any, will be
6870     * written in the output stream of the specified socket.
6871     *
6872     * The parameters must follow this syntax:
6873     * windowHashcode extra
6874     *
6875     * Where XX is the length in characeters of the windowTitle.
6876     *
6877     * The first parameter is the target window. The window with the specified hashcode
6878     * will be the target. If no target can be found, nothing happens. The extra parameters
6879     * will be delivered to the target window and as parameters to the command itself.
6880     *
6881     * @param client The remote client to sent the result, if any, to.
6882     * @param command The command to execute.
6883     * @param parameters The command parameters.
6884     *
6885     * @return True if the command was successfully delivered, false otherwise. This does
6886     *         not indicate whether the command itself was successful.
6887     */
6888    boolean viewServerWindowCommand(Socket client, String command, String parameters) {
6889        if (isSystemSecure()) {
6890            return false;
6891        }
6892
6893        boolean success = true;
6894        Parcel data = null;
6895        Parcel reply = null;
6896
6897        BufferedWriter out = null;
6898
6899        // Any uncaught exception will crash the system process
6900        try {
6901            // Find the hashcode of the window
6902            int index = parameters.indexOf(' ');
6903            if (index == -1) {
6904                index = parameters.length();
6905            }
6906            final String code = parameters.substring(0, index);
6907            int hashCode = (int) Long.parseLong(code, 16);
6908
6909            // Extract the command's parameter after the window description
6910            if (index < parameters.length()) {
6911                parameters = parameters.substring(index + 1);
6912            } else {
6913                parameters = "";
6914            }
6915
6916            final WindowState window = findWindow(hashCode);
6917            if (window == null) {
6918                return false;
6919            }
6920
6921            data = Parcel.obtain();
6922            data.writeInterfaceToken("android.view.IWindow");
6923            data.writeString(command);
6924            data.writeString(parameters);
6925            data.writeInt(1);
6926            ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0);
6927
6928            reply = Parcel.obtain();
6929
6930            final IBinder binder = window.mClient.asBinder();
6931            // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER
6932            binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
6933
6934            reply.readException();
6935
6936            if (!client.isOutputShutdown()) {
6937                out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
6938                out.write("DONE\n");
6939                out.flush();
6940            }
6941
6942        } catch (Exception e) {
6943            Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e);
6944            success = false;
6945        } finally {
6946            if (data != null) {
6947                data.recycle();
6948            }
6949            if (reply != null) {
6950                reply.recycle();
6951            }
6952            if (out != null) {
6953                try {
6954                    out.close();
6955                } catch (IOException e) {
6956
6957                }
6958            }
6959        }
6960
6961        return success;
6962    }
6963
6964    public void addWindowChangeListener(WindowChangeListener listener) {
6965        synchronized(mWindowMap) {
6966            mWindowChangeListeners.add(listener);
6967        }
6968    }
6969
6970    public void removeWindowChangeListener(WindowChangeListener listener) {
6971        synchronized(mWindowMap) {
6972            mWindowChangeListeners.remove(listener);
6973        }
6974    }
6975
6976    private void notifyWindowsChanged() {
6977        WindowChangeListener[] windowChangeListeners;
6978        synchronized(mWindowMap) {
6979            if(mWindowChangeListeners.isEmpty()) {
6980                return;
6981            }
6982            windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
6983            windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
6984        }
6985        int N = windowChangeListeners.length;
6986        for(int i = 0; i < N; i++) {
6987            windowChangeListeners[i].windowsChanged();
6988        }
6989    }
6990
6991    private void notifyFocusChanged() {
6992        WindowChangeListener[] windowChangeListeners;
6993        synchronized(mWindowMap) {
6994            if(mWindowChangeListeners.isEmpty()) {
6995                return;
6996            }
6997            windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
6998            windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
6999        }
7000        int N = windowChangeListeners.length;
7001        for(int i = 0; i < N; i++) {
7002            windowChangeListeners[i].focusChanged();
7003        }
7004    }
7005
7006    private WindowState findWindow(int hashCode) {
7007        if (hashCode == -1) {
7008            // TODO(multidisplay): Extend to multiple displays.
7009            return getFocusedWindow();
7010        }
7011
7012        synchronized (mWindowMap) {
7013            final int numDisplays = mDisplayContents.size();
7014            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
7015                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
7016                final int numWindows = windows.size();
7017                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
7018                    final WindowState w = windows.get(winNdx);
7019                    if (System.identityHashCode(w) == hashCode) {
7020                        return w;
7021                    }
7022                }
7023            }
7024        }
7025
7026        return null;
7027    }
7028
7029    /*
7030     * Instruct the Activity Manager to fetch the current configuration and broadcast
7031     * that to config-changed listeners if appropriate.
7032     */
7033    void sendNewConfiguration() {
7034        try {
7035            mActivityManager.updateConfiguration(null);
7036        } catch (RemoteException e) {
7037        }
7038    }
7039
7040    public Configuration computeNewConfiguration() {
7041        synchronized (mWindowMap) {
7042            Configuration config = computeNewConfigurationLocked();
7043            if (config == null && mWaitingForConfig) {
7044                // Nothing changed but we are waiting for something... stop that!
7045                mWaitingForConfig = false;
7046                mLastFinishedFreezeSource = "new-config";
7047                performLayoutAndPlaceSurfacesLocked();
7048            }
7049            return config;
7050        }
7051    }
7052
7053    Configuration computeNewConfigurationLocked() {
7054        Configuration config = new Configuration();
7055        config.fontScale = 0;
7056        if (!computeScreenConfigurationLocked(config)) {
7057            return null;
7058        }
7059        return config;
7060    }
7061
7062    private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int dw, int dh) {
7063        // TODO: Multidisplay: for now only use with default display.
7064        final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation);
7065        if (width < displayInfo.smallestNominalAppWidth) {
7066            displayInfo.smallestNominalAppWidth = width;
7067        }
7068        if (width > displayInfo.largestNominalAppWidth) {
7069            displayInfo.largestNominalAppWidth = width;
7070        }
7071        final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation);
7072        if (height < displayInfo.smallestNominalAppHeight) {
7073            displayInfo.smallestNominalAppHeight = height;
7074        }
7075        if (height > displayInfo.largestNominalAppHeight) {
7076            displayInfo.largestNominalAppHeight = height;
7077        }
7078    }
7079
7080    private int reduceConfigLayout(int curLayout, int rotation, float density,
7081            int dw, int dh) {
7082        // TODO: Multidisplay: for now only use with default display.
7083        // Get the app screen size at this rotation.
7084        int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation);
7085        int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation);
7086
7087        // Compute the screen layout size class for this rotation.
7088        int longSize = w;
7089        int shortSize = h;
7090        if (longSize < shortSize) {
7091            int tmp = longSize;
7092            longSize = shortSize;
7093            shortSize = tmp;
7094        }
7095        longSize = (int)(longSize/density);
7096        shortSize = (int)(shortSize/density);
7097        return Configuration.reduceScreenLayout(curLayout, longSize, shortSize);
7098    }
7099
7100    private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated,
7101                  int dw, int dh, float density, Configuration outConfig) {
7102        // TODO: Multidisplay: for now only use with default display.
7103
7104        // We need to determine the smallest width that will occur under normal
7105        // operation.  To this, start with the base screen size and compute the
7106        // width under the different possible rotations.  We need to un-rotate
7107        // the current screen dimensions before doing this.
7108        int unrotDw, unrotDh;
7109        if (rotated) {
7110            unrotDw = dh;
7111            unrotDh = dw;
7112        } else {
7113            unrotDw = dw;
7114            unrotDh = dh;
7115        }
7116        displayInfo.smallestNominalAppWidth = 1<<30;
7117        displayInfo.smallestNominalAppHeight = 1<<30;
7118        displayInfo.largestNominalAppWidth = 0;
7119        displayInfo.largestNominalAppHeight = 0;
7120        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, unrotDw, unrotDh);
7121        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, unrotDh, unrotDw);
7122        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, unrotDw, unrotDh);
7123        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, unrotDh, unrotDw);
7124        int sl = Configuration.resetScreenLayout(outConfig.screenLayout);
7125        sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh);
7126        sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw);
7127        sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh);
7128        sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw);
7129        outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density);
7130        outConfig.screenLayout = sl;
7131    }
7132
7133    private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm,
7134            int dw, int dh) {
7135        // TODO: Multidisplay: for now only use with default display.
7136        dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation);
7137        dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation);
7138        float scale = CompatibilityInfo.computeCompatibleScaling(dm, null);
7139        int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f);
7140        if (curSize == 0 || size < curSize) {
7141            curSize = size;
7142        }
7143        return curSize;
7144    }
7145
7146    private int computeCompatSmallestWidth(boolean rotated, DisplayMetrics dm, int dw, int dh) {
7147        // TODO: Multidisplay: for now only use with default display.
7148        mTmpDisplayMetrics.setTo(dm);
7149        final DisplayMetrics tmpDm = mTmpDisplayMetrics;
7150        final int unrotDw, unrotDh;
7151        if (rotated) {
7152            unrotDw = dh;
7153            unrotDh = dw;
7154        } else {
7155            unrotDw = dw;
7156            unrotDh = dh;
7157        }
7158        int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, tmpDm, unrotDw, unrotDh);
7159        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, tmpDm, unrotDh, unrotDw);
7160        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, tmpDm, unrotDw, unrotDh);
7161        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, tmpDm, unrotDh, unrotDw);
7162        return sw;
7163    }
7164
7165    boolean computeScreenConfigurationLocked(Configuration config) {
7166        if (!mDisplayReady) {
7167            return false;
7168        }
7169
7170        // TODO(multidisplay): For now, apply Configuration to main screen only.
7171        final DisplayContent displayContent = getDefaultDisplayContentLocked();
7172
7173        // Use the effective "visual" dimensions based on current rotation
7174        final boolean rotated = (mRotation == Surface.ROTATION_90
7175                || mRotation == Surface.ROTATION_270);
7176        final int realdw = rotated ?
7177                displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth;
7178        final int realdh = rotated ?
7179                displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight;
7180        int dw = realdw;
7181        int dh = realdh;
7182
7183        if (mAltOrientation) {
7184            if (realdw > realdh) {
7185                // Turn landscape into portrait.
7186                int maxw = (int)(realdh/1.3f);
7187                if (maxw < realdw) {
7188                    dw = maxw;
7189                }
7190            } else {
7191                // Turn portrait into landscape.
7192                int maxh = (int)(realdw/1.3f);
7193                if (maxh < realdh) {
7194                    dh = maxh;
7195                }
7196            }
7197        }
7198
7199        if (config != null) {
7200            config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT :
7201                    Configuration.ORIENTATION_LANDSCAPE;
7202        }
7203
7204        // Update application display metrics.
7205        final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation);
7206        final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation);
7207        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
7208        synchronized(displayContent.mDisplaySizeLock) {
7209            displayInfo.rotation = mRotation;
7210            displayInfo.logicalWidth = dw;
7211            displayInfo.logicalHeight = dh;
7212            displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity;
7213            displayInfo.appWidth = appWidth;
7214            displayInfo.appHeight = appHeight;
7215            displayInfo.getLogicalMetrics(mRealDisplayMetrics,
7216                    CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
7217            displayInfo.getAppMetrics(mDisplayMetrics);
7218            mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
7219                    displayContent.getDisplayId(), displayInfo);
7220        }
7221        if (false) {
7222            Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight);
7223        }
7224
7225        final DisplayMetrics dm = mDisplayMetrics;
7226        mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm,
7227                mCompatDisplayMetrics);
7228
7229        if (config != null) {
7230            config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation)
7231                    / dm.density);
7232            config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation)
7233                    / dm.density);
7234            computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, dm.density, config);
7235
7236            config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale);
7237            config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale);
7238            config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh);
7239            config.densityDpi = displayContent.mBaseDisplayDensity;
7240
7241            // Update the configuration based on available input devices, lid switch,
7242            // and platform configuration.
7243            config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
7244            config.keyboard = Configuration.KEYBOARD_NOKEYS;
7245            config.navigation = Configuration.NAVIGATION_NONAV;
7246
7247            int keyboardPresence = 0;
7248            int navigationPresence = 0;
7249            final InputDevice[] devices = mInputManager.getInputDevices();
7250            final int len = devices.length;
7251            for (int i = 0; i < len; i++) {
7252                InputDevice device = devices[i];
7253                if (!device.isVirtual()) {
7254                    final int sources = device.getSources();
7255                    final int presenceFlag = device.isExternal() ?
7256                            WindowManagerPolicy.PRESENCE_EXTERNAL :
7257                                    WindowManagerPolicy.PRESENCE_INTERNAL;
7258
7259                    if (mIsTouchDevice) {
7260                        if ((sources & InputDevice.SOURCE_TOUCHSCREEN) ==
7261                                InputDevice.SOURCE_TOUCHSCREEN) {
7262                            config.touchscreen = Configuration.TOUCHSCREEN_FINGER;
7263                        }
7264                    } else {
7265                        config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
7266                    }
7267
7268                    if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) {
7269                        config.navigation = Configuration.NAVIGATION_TRACKBALL;
7270                        navigationPresence |= presenceFlag;
7271                    } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD
7272                            && config.navigation == Configuration.NAVIGATION_NONAV) {
7273                        config.navigation = Configuration.NAVIGATION_DPAD;
7274                        navigationPresence |= presenceFlag;
7275                    }
7276
7277                    if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {
7278                        config.keyboard = Configuration.KEYBOARD_QWERTY;
7279                        keyboardPresence |= presenceFlag;
7280                    }
7281                }
7282            }
7283
7284            if (config.navigation == Configuration.NAVIGATION_NONAV && mHasPermanentDpad) {
7285                config.navigation = Configuration.NAVIGATION_DPAD;
7286                navigationPresence |= WindowManagerPolicy.PRESENCE_INTERNAL;
7287            }
7288
7289            // Determine whether a hard keyboard is available and enabled.
7290            boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS;
7291            if (hardKeyboardAvailable != mHardKeyboardAvailable) {
7292                mHardKeyboardAvailable = hardKeyboardAvailable;
7293                mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
7294                mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
7295            }
7296            if (mShowImeWithHardKeyboard) {
7297                config.keyboard = Configuration.KEYBOARD_NOKEYS;
7298            }
7299
7300            // Let the policy update hidden states.
7301            config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
7302            config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
7303            config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO;
7304            mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence);
7305        }
7306
7307        return true;
7308    }
7309
7310    public boolean isHardKeyboardAvailable() {
7311        synchronized (mWindowMap) {
7312            return mHardKeyboardAvailable;
7313        }
7314    }
7315
7316    public void updateShowImeWithHardKeyboard() {
7317        final boolean showImeWithHardKeyboard = Settings.Secure.getIntForUser(
7318                mContext.getContentResolver(), Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0,
7319                mCurrentUserId) == 1;
7320        synchronized (mWindowMap) {
7321            if (mShowImeWithHardKeyboard != showImeWithHardKeyboard) {
7322                mShowImeWithHardKeyboard = showImeWithHardKeyboard;
7323                mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
7324            }
7325        }
7326    }
7327
7328    public void setOnHardKeyboardStatusChangeListener(
7329            OnHardKeyboardStatusChangeListener listener) {
7330        synchronized (mWindowMap) {
7331            mHardKeyboardStatusChangeListener = listener;
7332        }
7333    }
7334
7335    void notifyHardKeyboardStatusChange() {
7336        final boolean available;
7337        final OnHardKeyboardStatusChangeListener listener;
7338        synchronized (mWindowMap) {
7339            listener = mHardKeyboardStatusChangeListener;
7340            available = mHardKeyboardAvailable;
7341        }
7342        if (listener != null) {
7343            listener.onHardKeyboardStatusChange(available);
7344        }
7345    }
7346
7347    // -------------------------------------------------------------
7348    // Drag and drop
7349    // -------------------------------------------------------------
7350
7351    IBinder prepareDragSurface(IWindow window, SurfaceSession session,
7352            int flags, int width, int height, Surface outSurface) {
7353        if (DEBUG_DRAG) {
7354            Slog.d(TAG, "prepare drag surface: w=" + width + " h=" + height
7355                    + " flags=" + Integer.toHexString(flags) + " win=" + window
7356                    + " asbinder=" + window.asBinder());
7357        }
7358
7359        final int callerPid = Binder.getCallingPid();
7360        final long origId = Binder.clearCallingIdentity();
7361        IBinder token = null;
7362
7363        try {
7364            synchronized (mWindowMap) {
7365                try {
7366                    if (mDragState == null) {
7367                        // TODO(multi-display): support other displays
7368                        final DisplayContent displayContent = getDefaultDisplayContentLocked();
7369                        final Display display = displayContent.getDisplay();
7370                        SurfaceControl surface = new SurfaceControl(session, "drag surface",
7371                                width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
7372                        surface.setLayerStack(display.getLayerStack());
7373                        if (SHOW_TRANSACTIONS) Slog.i(TAG, "  DRAG "
7374                                + surface + ": CREATE");
7375                        outSurface.copyFrom(surface);
7376                        final IBinder winBinder = window.asBinder();
7377                        token = new Binder();
7378                        mDragState = new DragState(this, token, surface, /*flags*/ 0, winBinder);
7379                        token = mDragState.mToken = new Binder();
7380
7381                        // 5 second timeout for this window to actually begin the drag
7382                        mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder);
7383                        Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder);
7384                        mH.sendMessageDelayed(msg, 5000);
7385                    } else {
7386                        Slog.w(TAG, "Drag already in progress");
7387                    }
7388                } catch (OutOfResourcesException e) {
7389                    Slog.e(TAG, "Can't allocate drag surface w=" + width + " h=" + height, e);
7390                    if (mDragState != null) {
7391                        mDragState.reset();
7392                        mDragState = null;
7393                    }
7394                }
7395            }
7396        } finally {
7397            Binder.restoreCallingIdentity(origId);
7398        }
7399
7400        return token;
7401    }
7402
7403    // -------------------------------------------------------------
7404    // Input Events and Focus Management
7405    // -------------------------------------------------------------
7406
7407    final InputMonitor mInputMonitor = new InputMonitor(this);
7408    private boolean mEventDispatchingEnabled;
7409
7410    @Override
7411    public void pauseKeyDispatching(IBinder _token) {
7412        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
7413                "pauseKeyDispatching()")) {
7414            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
7415        }
7416
7417        synchronized (mWindowMap) {
7418            WindowToken token = mTokenMap.get(_token);
7419            if (token != null) {
7420                mInputMonitor.pauseDispatchingLw(token);
7421            }
7422        }
7423    }
7424
7425    @Override
7426    public void resumeKeyDispatching(IBinder _token) {
7427        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
7428                "resumeKeyDispatching()")) {
7429            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
7430        }
7431
7432        synchronized (mWindowMap) {
7433            WindowToken token = mTokenMap.get(_token);
7434            if (token != null) {
7435                mInputMonitor.resumeDispatchingLw(token);
7436            }
7437        }
7438    }
7439
7440    @Override
7441    public void setEventDispatching(boolean enabled) {
7442        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
7443                "setEventDispatching()")) {
7444            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
7445        }
7446
7447        synchronized (mWindowMap) {
7448            mEventDispatchingEnabled = enabled;
7449            if (mDisplayEnabled) {
7450                mInputMonitor.setEventDispatchingLw(enabled);
7451            }
7452        }
7453    }
7454
7455    private WindowState getFocusedWindow() {
7456        synchronized (mWindowMap) {
7457            return getFocusedWindowLocked();
7458        }
7459    }
7460
7461    private WindowState getFocusedWindowLocked() {
7462        return mCurrentFocus;
7463    }
7464
7465    public boolean detectSafeMode() {
7466        if (!mInputMonitor.waitForInputDevicesReady(
7467                INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) {
7468            Slog.w(TAG, "Devices still not ready after waiting "
7469                   + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS
7470                   + " milliseconds before attempting to detect safe mode.");
7471        }
7472
7473        int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
7474                KeyEvent.KEYCODE_MENU);
7475        int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S);
7476        int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD,
7477                KeyEvent.KEYCODE_DPAD_CENTER);
7478        int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL,
7479                InputManagerService.BTN_MOUSE);
7480        int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
7481                KeyEvent.KEYCODE_VOLUME_DOWN);
7482        mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0
7483                || volumeDownState > 0;
7484        try {
7485            if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0) {
7486                mSafeMode = true;
7487                SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, "");
7488            }
7489        } catch (IllegalArgumentException e) {
7490        }
7491        if (mSafeMode) {
7492            Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState
7493                    + " dpad=" + dpadState + " trackball=" + trackballState + ")");
7494        } else {
7495            Log.i(TAG, "SAFE MODE not enabled");
7496        }
7497        mPolicy.setSafeMode(mSafeMode);
7498        return mSafeMode;
7499    }
7500
7501    public void displayReady() {
7502        displayReady(Display.DEFAULT_DISPLAY);
7503
7504        synchronized(mWindowMap) {
7505            final DisplayContent displayContent = getDefaultDisplayContentLocked();
7506            readForcedDisplaySizeAndDensityLocked(displayContent);
7507            mDisplayReady = true;
7508        }
7509
7510        try {
7511            mActivityManager.updateConfiguration(null);
7512        } catch (RemoteException e) {
7513        }
7514
7515        synchronized(mWindowMap) {
7516            mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
7517                    PackageManager.FEATURE_TOUCHSCREEN);
7518            configureDisplayPolicyLocked(getDefaultDisplayContentLocked());
7519        }
7520
7521        try {
7522            mActivityManager.updateConfiguration(null);
7523        } catch (RemoteException e) {
7524        }
7525    }
7526
7527    private void displayReady(int displayId) {
7528        synchronized(mWindowMap) {
7529            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7530            if (displayContent != null) {
7531                mAnimator.addDisplayLocked(displayId);
7532                synchronized(displayContent.mDisplaySizeLock) {
7533                    // Bootstrap the default logical display from the display manager.
7534                    final DisplayInfo displayInfo = displayContent.getDisplayInfo();
7535                    DisplayInfo newDisplayInfo = mDisplayManagerInternal.getDisplayInfo(displayId);
7536                    if (newDisplayInfo != null) {
7537                        displayInfo.copyFrom(newDisplayInfo);
7538                    }
7539                    displayContent.mInitialDisplayWidth = displayInfo.logicalWidth;
7540                    displayContent.mInitialDisplayHeight = displayInfo.logicalHeight;
7541                    displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi;
7542                    displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth;
7543                    displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight;
7544                    displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity;
7545                    displayContent.mBaseDisplayRect.set(0, 0,
7546                            displayContent.mBaseDisplayWidth, displayContent.mBaseDisplayHeight);
7547                }
7548            }
7549        }
7550    }
7551
7552    public void systemReady() {
7553        mPolicy.systemReady();
7554    }
7555
7556    // -------------------------------------------------------------
7557    // Async Handler
7558    // -------------------------------------------------------------
7559
7560    final class H extends Handler {
7561        public static final int REPORT_FOCUS_CHANGE = 2;
7562        public static final int REPORT_LOSING_FOCUS = 3;
7563        public static final int DO_TRAVERSAL = 4;
7564        public static final int ADD_STARTING = 5;
7565        public static final int REMOVE_STARTING = 6;
7566        public static final int FINISHED_STARTING = 7;
7567        public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8;
7568        public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9;
7569        public static final int WINDOW_FREEZE_TIMEOUT = 11;
7570
7571        public static final int APP_TRANSITION_TIMEOUT = 13;
7572        public static final int PERSIST_ANIMATION_SCALE = 14;
7573        public static final int FORCE_GC = 15;
7574        public static final int ENABLE_SCREEN = 16;
7575        public static final int APP_FREEZE_TIMEOUT = 17;
7576        public static final int SEND_NEW_CONFIGURATION = 18;
7577        public static final int REPORT_WINDOWS_CHANGE = 19;
7578        public static final int DRAG_START_TIMEOUT = 20;
7579        public static final int DRAG_END_TIMEOUT = 21;
7580        public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22;
7581        public static final int BOOT_TIMEOUT = 23;
7582        public static final int WAITING_FOR_DRAWN_TIMEOUT = 24;
7583        public static final int SHOW_STRICT_MODE_VIOLATION = 25;
7584        public static final int DO_ANIMATION_CALLBACK = 26;
7585
7586        public static final int DO_DISPLAY_ADDED = 27;
7587        public static final int DO_DISPLAY_REMOVED = 28;
7588        public static final int DO_DISPLAY_CHANGED = 29;
7589
7590        public static final int CLIENT_FREEZE_TIMEOUT = 30;
7591        public static final int TAP_OUTSIDE_STACK = 31;
7592        public static final int NOTIFY_ACTIVITY_DRAWN = 32;
7593
7594        public static final int ALL_WINDOWS_DRAWN = 33;
7595
7596        public static final int NEW_ANIMATOR_SCALE = 34;
7597
7598        public static final int SHOW_CIRCULAR_DISPLAY_MASK = 35;
7599        public static final int SHOW_EMULATOR_DISPLAY_OVERLAY = 36;
7600
7601        public static final int CHECK_IF_BOOT_ANIMATION_FINISHED = 37;
7602
7603        @Override
7604        public void handleMessage(Message msg) {
7605            if (DEBUG_WINDOW_TRACE) {
7606                Slog.v(TAG, "handleMessage: entry what=" + msg.what);
7607            }
7608            switch (msg.what) {
7609                case REPORT_FOCUS_CHANGE: {
7610                    WindowState lastFocus;
7611                    WindowState newFocus;
7612
7613                    synchronized(mWindowMap) {
7614                        lastFocus = mLastFocus;
7615                        newFocus = mCurrentFocus;
7616                        if (lastFocus == newFocus) {
7617                            // Focus is not changing, so nothing to do.
7618                            return;
7619                        }
7620                        mLastFocus = newFocus;
7621                        if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Focus moving from " + lastFocus +
7622                                " to " + newFocus);
7623                        if (newFocus != null && lastFocus != null
7624                                && !newFocus.isDisplayedLw()) {
7625                            //Slog.i(TAG, "Delaying loss of focus...");
7626                            mLosingFocus.add(lastFocus);
7627                            lastFocus = null;
7628                        }
7629                    }
7630
7631                    //System.out.println("Changing focus from " + lastFocus
7632                    //                   + " to " + newFocus);
7633                    if (newFocus != null) {
7634                        if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Gaining focus: " + newFocus);
7635                        newFocus.reportFocusChangedSerialized(true, mInTouchMode);
7636                        notifyFocusChanged();
7637                    }
7638
7639                    if (lastFocus != null) {
7640                        if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing focus: " + lastFocus);
7641                        lastFocus.reportFocusChangedSerialized(false, mInTouchMode);
7642                    }
7643                } break;
7644
7645                case REPORT_LOSING_FOCUS: {
7646                    ArrayList<WindowState> losers;
7647
7648                    synchronized(mWindowMap) {
7649                        losers = mLosingFocus;
7650                        mLosingFocus = new ArrayList<WindowState>();
7651                    }
7652
7653                    final int N = losers.size();
7654                    for (int i=0; i<N; i++) {
7655                        if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing delayed focus: " +
7656                                losers.get(i));
7657                        losers.get(i).reportFocusChangedSerialized(false, mInTouchMode);
7658                    }
7659                } break;
7660
7661                case DO_TRAVERSAL: {
7662                    synchronized(mWindowMap) {
7663                        mTraversalScheduled = false;
7664                        performLayoutAndPlaceSurfacesLocked();
7665                    }
7666                } break;
7667
7668                case ADD_STARTING: {
7669                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7670                    final StartingData sd = wtoken.startingData;
7671
7672                    if (sd == null) {
7673                        // Animation has been canceled... do nothing.
7674                        return;
7675                    }
7676
7677                    if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting "
7678                            + wtoken + ": pkg=" + sd.pkg);
7679
7680                    View view = null;
7681                    try {
7682                        view = mPolicy.addStartingWindow(
7683                            wtoken.token, sd.pkg, sd.theme, sd.compatInfo,
7684                            sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo, sd.windowFlags);
7685                    } catch (Exception e) {
7686                        Slog.w(TAG, "Exception when adding starting window", e);
7687                    }
7688
7689                    if (view != null) {
7690                        boolean abort = false;
7691
7692                        synchronized(mWindowMap) {
7693                            if (wtoken.removed || wtoken.startingData == null) {
7694                                // If the window was successfully added, then
7695                                // we need to remove it.
7696                                if (wtoken.startingWindow != null) {
7697                                    if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
7698                                            "Aborted starting " + wtoken
7699                                            + ": removed=" + wtoken.removed
7700                                            + " startingData=" + wtoken.startingData);
7701                                    wtoken.startingWindow = null;
7702                                    wtoken.startingData = null;
7703                                    abort = true;
7704                                }
7705                            } else {
7706                                wtoken.startingView = view;
7707                            }
7708                            if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG,
7709                                    "Added starting " + wtoken
7710                                    + ": startingWindow="
7711                                    + wtoken.startingWindow + " startingView="
7712                                    + wtoken.startingView);
7713                        }
7714
7715                        if (abort) {
7716                            try {
7717                                mPolicy.removeStartingWindow(wtoken.token, view);
7718                            } catch (Exception e) {
7719                                Slog.w(TAG, "Exception when removing starting window", e);
7720                            }
7721                        }
7722                    }
7723                } break;
7724
7725                case REMOVE_STARTING: {
7726                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7727                    IBinder token = null;
7728                    View view = null;
7729                    synchronized (mWindowMap) {
7730                        if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting "
7731                                + wtoken + ": startingWindow="
7732                                + wtoken.startingWindow + " startingView="
7733                                + wtoken.startingView);
7734                        if (wtoken.startingWindow != null) {
7735                            view = wtoken.startingView;
7736                            token = wtoken.token;
7737                            wtoken.startingData = null;
7738                            wtoken.startingView = null;
7739                            wtoken.startingWindow = null;
7740                            wtoken.startingDisplayed = false;
7741                        }
7742                    }
7743                    if (view != null) {
7744                        try {
7745                            mPolicy.removeStartingWindow(token, view);
7746                        } catch (Exception e) {
7747                            Slog.w(TAG, "Exception when removing starting window", e);
7748                        }
7749                    }
7750                } break;
7751
7752                case FINISHED_STARTING: {
7753                    IBinder token = null;
7754                    View view = null;
7755                    while (true) {
7756                        synchronized (mWindowMap) {
7757                            final int N = mFinishedStarting.size();
7758                            if (N <= 0) {
7759                                break;
7760                            }
7761                            AppWindowToken wtoken = mFinishedStarting.remove(N-1);
7762
7763                            if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
7764                                    "Finished starting " + wtoken
7765                                    + ": startingWindow=" + wtoken.startingWindow
7766                                    + " startingView=" + wtoken.startingView);
7767
7768                            if (wtoken.startingWindow == null) {
7769                                continue;
7770                            }
7771
7772                            view = wtoken.startingView;
7773                            token = wtoken.token;
7774                            wtoken.startingData = null;
7775                            wtoken.startingView = null;
7776                            wtoken.startingWindow = null;
7777                            wtoken.startingDisplayed = false;
7778                        }
7779
7780                        try {
7781                            mPolicy.removeStartingWindow(token, view);
7782                        } catch (Exception e) {
7783                            Slog.w(TAG, "Exception when removing starting window", e);
7784                        }
7785                    }
7786                } break;
7787
7788                case REPORT_APPLICATION_TOKEN_DRAWN: {
7789                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7790
7791                    try {
7792                        if (DEBUG_VISIBILITY) Slog.v(
7793                                TAG, "Reporting drawn in " + wtoken);
7794                        wtoken.appToken.windowsDrawn();
7795                    } catch (RemoteException ex) {
7796                    }
7797                } break;
7798
7799                case REPORT_APPLICATION_TOKEN_WINDOWS: {
7800                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7801
7802                    boolean nowVisible = msg.arg1 != 0;
7803                    boolean nowGone = msg.arg2 != 0;
7804
7805                    try {
7806                        if (DEBUG_VISIBILITY) Slog.v(
7807                                TAG, "Reporting visible in " + wtoken
7808                                + " visible=" + nowVisible
7809                                + " gone=" + nowGone);
7810                        if (nowVisible) {
7811                            wtoken.appToken.windowsVisible();
7812                        } else {
7813                            wtoken.appToken.windowsGone();
7814                        }
7815                    } catch (RemoteException ex) {
7816                    }
7817                } break;
7818
7819                case WINDOW_FREEZE_TIMEOUT: {
7820                    // TODO(multidisplay): Can non-default displays rotate?
7821                    synchronized (mWindowMap) {
7822                        Slog.w(TAG, "Window freeze timeout expired.");
7823                        final WindowList windows = getDefaultWindowListLocked();
7824                        int i = windows.size();
7825                        while (i > 0) {
7826                            i--;
7827                            WindowState w = windows.get(i);
7828                            if (w.mOrientationChanging) {
7829                                w.mOrientationChanging = false;
7830                                w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
7831                                        - mDisplayFreezeTime);
7832                                Slog.w(TAG, "Force clearing orientation change: " + w);
7833                            }
7834                        }
7835                        performLayoutAndPlaceSurfacesLocked();
7836                    }
7837                    break;
7838                }
7839
7840                case APP_TRANSITION_TIMEOUT: {
7841                    synchronized (mWindowMap) {
7842                        if (mAppTransition.isTransitionSet()) {
7843                            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** APP TRANSITION TIMEOUT");
7844                            mAppTransition.setTimeout();
7845                            performLayoutAndPlaceSurfacesLocked();
7846                        }
7847                    }
7848                    break;
7849                }
7850
7851                case PERSIST_ANIMATION_SCALE: {
7852                    Settings.Global.putFloat(mContext.getContentResolver(),
7853                            Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting);
7854                    Settings.Global.putFloat(mContext.getContentResolver(),
7855                            Settings.Global.TRANSITION_ANIMATION_SCALE,
7856                            mTransitionAnimationScaleSetting);
7857                    Settings.Global.putFloat(mContext.getContentResolver(),
7858                            Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting);
7859                    break;
7860                }
7861
7862                case FORCE_GC: {
7863                    synchronized (mWindowMap) {
7864                        // Since we're holding both mWindowMap and mAnimator we don't need to
7865                        // hold mAnimator.mLayoutToAnim.
7866                        if (mAnimator.mAnimating || mAnimationScheduled) {
7867                            // If we are animating, don't do the gc now but
7868                            // delay a bit so we don't interrupt the animation.
7869                            sendEmptyMessageDelayed(H.FORCE_GC, 2000);
7870                            return;
7871                        }
7872                        // If we are currently rotating the display, it will
7873                        // schedule a new message when done.
7874                        if (mDisplayFrozen) {
7875                            return;
7876                        }
7877                    }
7878                    Runtime.getRuntime().gc();
7879                    break;
7880                }
7881
7882                case ENABLE_SCREEN: {
7883                    performEnableScreen();
7884                    break;
7885                }
7886
7887                case APP_FREEZE_TIMEOUT: {
7888                    synchronized (mWindowMap) {
7889                        Slog.w(TAG, "App freeze timeout expired.");
7890                        final int numStacks = mStackIdToStack.size();
7891                        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
7892                            final TaskStack stack = mStackIdToStack.valueAt(stackNdx);
7893                            final ArrayList<Task> tasks = stack.getTasks();
7894                            for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
7895                                AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
7896                                for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
7897                                    AppWindowToken tok = tokens.get(tokenNdx);
7898                                    if (tok.mAppAnimator.freezingScreen) {
7899                                        Slog.w(TAG, "Force clearing freeze: " + tok);
7900                                        unsetAppFreezingScreenLocked(tok, true, true);
7901                                    }
7902                                }
7903                            }
7904                        }
7905                    }
7906                    break;
7907                }
7908
7909                case CLIENT_FREEZE_TIMEOUT: {
7910                    synchronized (mWindowMap) {
7911                        if (mClientFreezingScreen) {
7912                            mClientFreezingScreen = false;
7913                            mLastFinishedFreezeSource = "client-timeout";
7914                            stopFreezingDisplayLocked();
7915                        }
7916                    }
7917                    break;
7918                }
7919
7920                case SEND_NEW_CONFIGURATION: {
7921                    removeMessages(SEND_NEW_CONFIGURATION);
7922                    sendNewConfiguration();
7923                    break;
7924                }
7925
7926                case REPORT_WINDOWS_CHANGE: {
7927                    if (mWindowsChanged) {
7928                        synchronized (mWindowMap) {
7929                            mWindowsChanged = false;
7930                        }
7931                        notifyWindowsChanged();
7932                    }
7933                    break;
7934                }
7935
7936                case DRAG_START_TIMEOUT: {
7937                    IBinder win = (IBinder)msg.obj;
7938                    if (DEBUG_DRAG) {
7939                        Slog.w(TAG, "Timeout starting drag by win " + win);
7940                    }
7941                    synchronized (mWindowMap) {
7942                        // !!! TODO: ANR the app that has failed to start the drag in time
7943                        if (mDragState != null) {
7944                            mDragState.unregister();
7945                            mInputMonitor.updateInputWindowsLw(true /*force*/);
7946                            mDragState.reset();
7947                            mDragState = null;
7948                        }
7949                    }
7950                    break;
7951                }
7952
7953                case DRAG_END_TIMEOUT: {
7954                    IBinder win = (IBinder)msg.obj;
7955                    if (DEBUG_DRAG) {
7956                        Slog.w(TAG, "Timeout ending drag to win " + win);
7957                    }
7958                    synchronized (mWindowMap) {
7959                        // !!! TODO: ANR the drag-receiving app
7960                        if (mDragState != null) {
7961                            mDragState.mDragResult = false;
7962                            mDragState.endDragLw();
7963                        }
7964                    }
7965                    break;
7966                }
7967
7968                case REPORT_HARD_KEYBOARD_STATUS_CHANGE: {
7969                    notifyHardKeyboardStatusChange();
7970                    break;
7971                }
7972
7973                case BOOT_TIMEOUT: {
7974                    performBootTimeout();
7975                    break;
7976                }
7977
7978                case WAITING_FOR_DRAWN_TIMEOUT: {
7979                    Runnable callback = null;
7980                    synchronized (mWindowMap) {
7981                        Slog.w(TAG, "Timeout waiting for drawn: undrawn=" + mWaitingForDrawn);
7982                        mWaitingForDrawn.clear();
7983                        callback = mWaitingForDrawnCallback;
7984                        mWaitingForDrawnCallback = null;
7985                    }
7986                    if (callback != null) {
7987                        callback.run();
7988                    }
7989                    break;
7990                }
7991
7992                case SHOW_STRICT_MODE_VIOLATION: {
7993                    showStrictModeViolation(msg.arg1, msg.arg2);
7994                    break;
7995                }
7996
7997                case SHOW_CIRCULAR_DISPLAY_MASK: {
7998                    showCircularMask(msg.arg1 == 1);
7999                    break;
8000                }
8001
8002                case SHOW_EMULATOR_DISPLAY_OVERLAY: {
8003                    showEmulatorDisplayOverlay();
8004                    break;
8005                }
8006
8007                case DO_ANIMATION_CALLBACK: {
8008                    try {
8009                        ((IRemoteCallback)msg.obj).sendResult(null);
8010                    } catch (RemoteException e) {
8011                    }
8012                    break;
8013                }
8014
8015                case DO_DISPLAY_ADDED:
8016                    handleDisplayAdded(msg.arg1);
8017                    break;
8018
8019                case DO_DISPLAY_REMOVED:
8020                    synchronized (mWindowMap) {
8021                        handleDisplayRemovedLocked(msg.arg1);
8022                    }
8023                    break;
8024
8025                case DO_DISPLAY_CHANGED:
8026                    synchronized (mWindowMap) {
8027                        handleDisplayChangedLocked(msg.arg1);
8028                    }
8029                    break;
8030
8031                case TAP_OUTSIDE_STACK: {
8032                    int stackId;
8033                    synchronized (mWindowMap) {
8034                        stackId = ((DisplayContent)msg.obj).stackIdFromPoint(msg.arg1, msg.arg2);
8035                    }
8036                    if (stackId >= 0) {
8037                        try {
8038                            mActivityManager.setFocusedStack(stackId);
8039                        } catch (RemoteException e) {
8040                        }
8041                    }
8042                }
8043                break;
8044                case NOTIFY_ACTIVITY_DRAWN:
8045                    try {
8046                        mActivityManager.notifyActivityDrawn((IBinder) msg.obj);
8047                    } catch (RemoteException e) {
8048                    }
8049                    break;
8050                case ALL_WINDOWS_DRAWN: {
8051                    Runnable callback;
8052                    synchronized (mWindowMap) {
8053                        callback = mWaitingForDrawnCallback;
8054                        mWaitingForDrawnCallback = null;
8055                    }
8056                    if (callback != null) {
8057                        callback.run();
8058                    }
8059                }
8060                case NEW_ANIMATOR_SCALE: {
8061                    float scale = getCurrentAnimatorScale();
8062                    ValueAnimator.setDurationScale(scale);
8063                    Session session = (Session)msg.obj;
8064                    if (session != null) {
8065                        try {
8066                            session.mCallback.onAnimatorScaleChanged(scale);
8067                        } catch (RemoteException e) {
8068                        }
8069                    } else {
8070                        ArrayList<IWindowSessionCallback> callbacks
8071                                = new ArrayList<IWindowSessionCallback>();
8072                        synchronized (mWindowMap) {
8073                            for (int i=0; i<mSessions.size(); i++) {
8074                                callbacks.add(mSessions.valueAt(i).mCallback);
8075                            }
8076
8077                        }
8078                        for (int i=0; i<callbacks.size(); i++) {
8079                            try {
8080                                callbacks.get(i).onAnimatorScaleChanged(scale);
8081                            } catch (RemoteException e) {
8082                            }
8083                        }
8084                    }
8085                }
8086                break;
8087                case CHECK_IF_BOOT_ANIMATION_FINISHED: {
8088                    final boolean bootAnimationComplete;
8089                    synchronized (mWindowMap) {
8090                        if (DEBUG_BOOT) Slog.i(TAG, "CHECK_IF_BOOT_ANIMATION_FINISHED:");
8091                        bootAnimationComplete = checkBootAnimationCompleteLocked();
8092                    }
8093                    if (bootAnimationComplete) {
8094                        performEnableScreen();
8095                    }
8096                }
8097                break;
8098            }
8099            if (DEBUG_WINDOW_TRACE) {
8100                Slog.v(TAG, "handleMessage: exit");
8101            }
8102        }
8103    }
8104
8105    // -------------------------------------------------------------
8106    // IWindowManager API
8107    // -------------------------------------------------------------
8108
8109    @Override
8110    public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client,
8111            IInputContext inputContext) {
8112        if (client == null) throw new IllegalArgumentException("null client");
8113        if (inputContext == null) throw new IllegalArgumentException("null inputContext");
8114        Session session = new Session(this, callback, client, inputContext);
8115        return session;
8116    }
8117
8118    @Override
8119    public boolean inputMethodClientHasFocus(IInputMethodClient client) {
8120        synchronized (mWindowMap) {
8121            // The focus for the client is the window immediately below
8122            // where we would place the input method window.
8123            int idx = findDesiredInputMethodWindowIndexLocked(false);
8124            if (idx > 0) {
8125                // TODO(multidisplay): IMEs are only supported on the default display.
8126                WindowState imFocus = getDefaultWindowListLocked().get(idx-1);
8127                if (DEBUG_INPUT_METHOD) {
8128                    Slog.i(TAG, "Desired input method target: " + imFocus);
8129                    Slog.i(TAG, "Current focus: " + mCurrentFocus);
8130                    Slog.i(TAG, "Last focus: " + mLastFocus);
8131                }
8132                if (imFocus != null) {
8133                    // This may be a starting window, in which case we still want
8134                    // to count it as okay.
8135                    if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING
8136                            && imFocus.mAppToken != null) {
8137                        // The client has definitely started, so it really should
8138                        // have a window in this app token.  Let's look for it.
8139                        for (int i=0; i<imFocus.mAppToken.windows.size(); i++) {
8140                            WindowState w = imFocus.mAppToken.windows.get(i);
8141                            if (w != imFocus) {
8142                                Log.i(TAG, "Switching to real app window: " + w);
8143                                imFocus = w;
8144                                break;
8145                            }
8146                        }
8147                    }
8148                    if (DEBUG_INPUT_METHOD) {
8149                        Slog.i(TAG, "IM target client: " + imFocus.mSession.mClient);
8150                        if (imFocus.mSession.mClient != null) {
8151                            Slog.i(TAG, "IM target client binder: "
8152                                    + imFocus.mSession.mClient.asBinder());
8153                            Slog.i(TAG, "Requesting client binder: " + client.asBinder());
8154                        }
8155                    }
8156                    if (imFocus.mSession.mClient != null &&
8157                            imFocus.mSession.mClient.asBinder() == client.asBinder()) {
8158                        return true;
8159                    }
8160                }
8161            }
8162
8163            // Okay, how about this...  what is the current focus?
8164            // It seems in some cases we may not have moved the IM
8165            // target window, such as when it was in a pop-up window,
8166            // so let's also look at the current focus.  (An example:
8167            // go to Gmail, start searching so the keyboard goes up,
8168            // press home.  Sometimes the IME won't go down.)
8169            // Would be nice to fix this more correctly, but it's
8170            // way at the end of a release, and this should be good enough.
8171            if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null
8172                    && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) {
8173                return true;
8174            }
8175        }
8176        return false;
8177    }
8178
8179    @Override
8180    public void getInitialDisplaySize(int displayId, Point size) {
8181        synchronized (mWindowMap) {
8182            final DisplayContent displayContent = getDisplayContentLocked(displayId);
8183            if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
8184                synchronized(displayContent.mDisplaySizeLock) {
8185                    size.x = displayContent.mInitialDisplayWidth;
8186                    size.y = displayContent.mInitialDisplayHeight;
8187                }
8188            }
8189        }
8190    }
8191
8192    @Override
8193    public void getBaseDisplaySize(int displayId, Point size) {
8194        synchronized (mWindowMap) {
8195            final DisplayContent displayContent = getDisplayContentLocked(displayId);
8196            if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
8197                synchronized(displayContent.mDisplaySizeLock) {
8198                    size.x = displayContent.mBaseDisplayWidth;
8199                    size.y = displayContent.mBaseDisplayHeight;
8200                }
8201            }
8202        }
8203    }
8204
8205    @Override
8206    public void setForcedDisplaySize(int displayId, int width, int height) {
8207        if (mContext.checkCallingOrSelfPermission(
8208                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
8209                PackageManager.PERMISSION_GRANTED) {
8210            throw new SecurityException("Must hold permission " +
8211                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
8212        }
8213        if (displayId != Display.DEFAULT_DISPLAY) {
8214            throw new IllegalArgumentException("Can only set the default display");
8215        }
8216        final long ident = Binder.clearCallingIdentity();
8217        try {
8218            synchronized(mWindowMap) {
8219                // Set some sort of reasonable bounds on the size of the display that we
8220                // will try to emulate.
8221                final int MIN_WIDTH = 200;
8222                final int MIN_HEIGHT = 200;
8223                final int MAX_SCALE = 2;
8224                final DisplayContent displayContent = getDisplayContentLocked(displayId);
8225                if (displayContent != null) {
8226                    width = Math.min(Math.max(width, MIN_WIDTH),
8227                            displayContent.mInitialDisplayWidth * MAX_SCALE);
8228                    height = Math.min(Math.max(height, MIN_HEIGHT),
8229                            displayContent.mInitialDisplayHeight * MAX_SCALE);
8230                    setForcedDisplaySizeLocked(displayContent, width, height);
8231                    Settings.Global.putString(mContext.getContentResolver(),
8232                            Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height);
8233                }
8234            }
8235        } finally {
8236            Binder.restoreCallingIdentity(ident);
8237        }
8238    }
8239
8240    private void readForcedDisplaySizeAndDensityLocked(final DisplayContent displayContent) {
8241        String sizeStr = Settings.Global.getString(mContext.getContentResolver(),
8242                Settings.Global.DISPLAY_SIZE_FORCED);
8243        if (sizeStr == null || sizeStr.length() == 0) {
8244            sizeStr = SystemProperties.get(SIZE_OVERRIDE, null);
8245        }
8246        if (sizeStr != null && sizeStr.length() > 0) {
8247            final int pos = sizeStr.indexOf(',');
8248            if (pos > 0 && sizeStr.lastIndexOf(',') == pos) {
8249                int width, height;
8250                try {
8251                    width = Integer.parseInt(sizeStr.substring(0, pos));
8252                    height = Integer.parseInt(sizeStr.substring(pos+1));
8253                    synchronized(displayContent.mDisplaySizeLock) {
8254                        if (displayContent.mBaseDisplayWidth != width
8255                                || displayContent.mBaseDisplayHeight != height) {
8256                            Slog.i(TAG, "FORCED DISPLAY SIZE: " + width + "x" + height);
8257                            displayContent.mBaseDisplayWidth = width;
8258                            displayContent.mBaseDisplayHeight = height;
8259                        }
8260                    }
8261                } catch (NumberFormatException ex) {
8262                }
8263            }
8264        }
8265        String densityStr = Settings.Global.getString(mContext.getContentResolver(),
8266                Settings.Global.DISPLAY_DENSITY_FORCED);
8267        if (densityStr == null || densityStr.length() == 0) {
8268            densityStr = SystemProperties.get(DENSITY_OVERRIDE, null);
8269        }
8270        if (densityStr != null && densityStr.length() > 0) {
8271            int density;
8272            try {
8273                density = Integer.parseInt(densityStr);
8274                synchronized(displayContent.mDisplaySizeLock) {
8275                    if (displayContent.mBaseDisplayDensity != density) {
8276                        Slog.i(TAG, "FORCED DISPLAY DENSITY: " + density);
8277                        displayContent.mBaseDisplayDensity = density;
8278                    }
8279                }
8280            } catch (NumberFormatException ex) {
8281            }
8282        }
8283    }
8284
8285    // displayContent must not be null
8286    private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {
8287        Slog.i(TAG, "Using new display size: " + width + "x" + height);
8288
8289        synchronized(displayContent.mDisplaySizeLock) {
8290            displayContent.mBaseDisplayWidth = width;
8291            displayContent.mBaseDisplayHeight = height;
8292        }
8293        reconfigureDisplayLocked(displayContent);
8294    }
8295
8296    @Override
8297    public void clearForcedDisplaySize(int displayId) {
8298        if (mContext.checkCallingOrSelfPermission(
8299                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
8300                PackageManager.PERMISSION_GRANTED) {
8301            throw new SecurityException("Must hold permission " +
8302                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
8303        }
8304        if (displayId != Display.DEFAULT_DISPLAY) {
8305            throw new IllegalArgumentException("Can only set the default display");
8306        }
8307        final long ident = Binder.clearCallingIdentity();
8308        try {
8309            synchronized(mWindowMap) {
8310                final DisplayContent displayContent = getDisplayContentLocked(displayId);
8311                if (displayContent != null) {
8312                    setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
8313                            displayContent.mInitialDisplayHeight);
8314                    Settings.Global.putString(mContext.getContentResolver(),
8315                            Settings.Global.DISPLAY_SIZE_FORCED, "");
8316                }
8317            }
8318        } finally {
8319            Binder.restoreCallingIdentity(ident);
8320        }
8321    }
8322
8323    @Override
8324    public int getInitialDisplayDensity(int displayId) {
8325        synchronized (mWindowMap) {
8326            final DisplayContent displayContent = getDisplayContentLocked(displayId);
8327            if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
8328                synchronized(displayContent.mDisplaySizeLock) {
8329                    return displayContent.mInitialDisplayDensity;
8330                }
8331            }
8332        }
8333        return -1;
8334    }
8335
8336    @Override
8337    public int getBaseDisplayDensity(int displayId) {
8338        synchronized (mWindowMap) {
8339            final DisplayContent displayContent = getDisplayContentLocked(displayId);
8340            if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
8341                synchronized(displayContent.mDisplaySizeLock) {
8342                    return displayContent.mBaseDisplayDensity;
8343                }
8344            }
8345        }
8346        return -1;
8347    }
8348
8349    @Override
8350    public void setForcedDisplayDensity(int displayId, int density) {
8351        if (mContext.checkCallingOrSelfPermission(
8352                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
8353                PackageManager.PERMISSION_GRANTED) {
8354            throw new SecurityException("Must hold permission " +
8355                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
8356        }
8357        if (displayId != Display.DEFAULT_DISPLAY) {
8358            throw new IllegalArgumentException("Can only set the default display");
8359        }
8360        final long ident = Binder.clearCallingIdentity();
8361        try {
8362            synchronized(mWindowMap) {
8363                final DisplayContent displayContent = getDisplayContentLocked(displayId);
8364                if (displayContent != null) {
8365                    setForcedDisplayDensityLocked(displayContent, density);
8366                    Settings.Global.putString(mContext.getContentResolver(),
8367                            Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density));
8368                }
8369            }
8370        } finally {
8371            Binder.restoreCallingIdentity(ident);
8372        }
8373    }
8374
8375    // displayContent must not be null
8376    private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) {
8377        Slog.i(TAG, "Using new display density: " + density);
8378
8379        synchronized(displayContent.mDisplaySizeLock) {
8380            displayContent.mBaseDisplayDensity = density;
8381        }
8382        reconfigureDisplayLocked(displayContent);
8383    }
8384
8385    @Override
8386    public void clearForcedDisplayDensity(int displayId) {
8387        if (mContext.checkCallingOrSelfPermission(
8388                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
8389                PackageManager.PERMISSION_GRANTED) {
8390            throw new SecurityException("Must hold permission " +
8391                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
8392        }
8393        if (displayId != Display.DEFAULT_DISPLAY) {
8394            throw new IllegalArgumentException("Can only set the default display");
8395        }
8396        final long ident = Binder.clearCallingIdentity();
8397        try {
8398            synchronized(mWindowMap) {
8399                final DisplayContent displayContent = getDisplayContentLocked(displayId);
8400                if (displayContent != null) {
8401                    setForcedDisplayDensityLocked(displayContent,
8402                            displayContent.mInitialDisplayDensity);
8403                    Settings.Global.putString(mContext.getContentResolver(),
8404                            Settings.Global.DISPLAY_DENSITY_FORCED, "");
8405                }
8406            }
8407        } finally {
8408            Binder.restoreCallingIdentity(ident);
8409        }
8410    }
8411
8412    // displayContent must not be null
8413    private void reconfigureDisplayLocked(DisplayContent displayContent) {
8414        // TODO: Multidisplay: for now only use with default display.
8415        configureDisplayPolicyLocked(displayContent);
8416        displayContent.layoutNeeded = true;
8417
8418        boolean configChanged = updateOrientationFromAppTokensLocked(false);
8419        mTempConfiguration.setToDefaults();
8420        mTempConfiguration.fontScale = mCurConfiguration.fontScale;
8421        if (computeScreenConfigurationLocked(mTempConfiguration)) {
8422            if (mCurConfiguration.diff(mTempConfiguration) != 0) {
8423                configChanged = true;
8424            }
8425        }
8426
8427        if (configChanged) {
8428            mWaitingForConfig = true;
8429            startFreezingDisplayLocked(false, 0, 0);
8430            mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
8431        }
8432
8433        performLayoutAndPlaceSurfacesLocked();
8434    }
8435
8436    private void configureDisplayPolicyLocked(DisplayContent displayContent) {
8437        mPolicy.setInitialDisplaySize(displayContent.getDisplay(),
8438                displayContent.mBaseDisplayWidth,
8439                displayContent.mBaseDisplayHeight,
8440                displayContent.mBaseDisplayDensity);
8441
8442        DisplayInfo displayInfo = displayContent.getDisplayInfo();
8443        mPolicy.setDisplayOverscan(displayContent.getDisplay(),
8444                displayInfo.overscanLeft, displayInfo.overscanTop,
8445                displayInfo.overscanRight, displayInfo.overscanBottom);
8446    }
8447
8448    @Override
8449    public void setOverscan(int displayId, int left, int top, int right, int bottom) {
8450        if (mContext.checkCallingOrSelfPermission(
8451                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
8452                PackageManager.PERMISSION_GRANTED) {
8453            throw new SecurityException("Must hold permission " +
8454                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
8455        }
8456        final long ident = Binder.clearCallingIdentity();
8457        try {
8458            synchronized(mWindowMap) {
8459                DisplayContent displayContent = getDisplayContentLocked(displayId);
8460                if (displayContent != null) {
8461                    setOverscanLocked(displayContent, left, top, right, bottom);
8462                }
8463            }
8464        } finally {
8465            Binder.restoreCallingIdentity(ident);
8466        }
8467    }
8468
8469    private void setOverscanLocked(DisplayContent displayContent,
8470            int left, int top, int right, int bottom) {
8471        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
8472        synchronized (displayContent.mDisplaySizeLock) {
8473            displayInfo.overscanLeft = left;
8474            displayInfo.overscanTop = top;
8475            displayInfo.overscanRight = right;
8476            displayInfo.overscanBottom = bottom;
8477        }
8478
8479        mDisplaySettings.setOverscanLocked(displayInfo.uniqueId, left, top, right, bottom);
8480        mDisplaySettings.writeSettingsLocked();
8481
8482        reconfigureDisplayLocked(displayContent);
8483    }
8484
8485    // -------------------------------------------------------------
8486    // Internals
8487    // -------------------------------------------------------------
8488
8489    final WindowState windowForClientLocked(Session session, IWindow client,
8490            boolean throwOnError) {
8491        return windowForClientLocked(session, client.asBinder(), throwOnError);
8492    }
8493
8494    final WindowState windowForClientLocked(Session session, IBinder client,
8495            boolean throwOnError) {
8496        WindowState win = mWindowMap.get(client);
8497        if (localLOGV) Slog.v(
8498            TAG, "Looking up client " + client + ": " + win);
8499        if (win == null) {
8500            RuntimeException ex = new IllegalArgumentException(
8501                    "Requested window " + client + " does not exist");
8502            if (throwOnError) {
8503                throw ex;
8504            }
8505            Slog.w(TAG, "Failed looking up window", ex);
8506            return null;
8507        }
8508        if (session != null && win.mSession != session) {
8509            RuntimeException ex = new IllegalArgumentException(
8510                    "Requested window " + client + " is in session " +
8511                    win.mSession + ", not " + session);
8512            if (throwOnError) {
8513                throw ex;
8514            }
8515            Slog.w(TAG, "Failed looking up window", ex);
8516            return null;
8517        }
8518
8519        return win;
8520    }
8521
8522    final void rebuildAppWindowListLocked() {
8523        rebuildAppWindowListLocked(getDefaultDisplayContentLocked());
8524    }
8525
8526    private void rebuildAppWindowListLocked(final DisplayContent displayContent) {
8527        final WindowList windows = displayContent.getWindowList();
8528        int NW = windows.size();
8529        int i;
8530        int lastBelow = -1;
8531        int numRemoved = 0;
8532
8533        if (mRebuildTmp.length < NW) {
8534            mRebuildTmp = new WindowState[NW+10];
8535        }
8536
8537        // First remove all existing app windows.
8538        i=0;
8539        while (i < NW) {
8540            WindowState w = windows.get(i);
8541            if (w.mAppToken != null) {
8542                WindowState win = windows.remove(i);
8543                win.mRebuilding = true;
8544                mRebuildTmp[numRemoved] = win;
8545                mWindowsChanged = true;
8546                if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Rebuild removing window: " + win);
8547                NW--;
8548                numRemoved++;
8549                continue;
8550            } else if (lastBelow == i-1) {
8551                if (w.mAttrs.type == TYPE_WALLPAPER || w.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
8552                    lastBelow = i;
8553                }
8554            }
8555            i++;
8556        }
8557
8558        // Keep whatever windows were below the app windows still below,
8559        // by skipping them.
8560        lastBelow++;
8561        i = lastBelow;
8562
8563        // First add all of the exiting app tokens...  these are no longer
8564        // in the main app list, but still have windows shown.  We put them
8565        // in the back because now that the animation is over we no longer
8566        // will care about them.
8567        final ArrayList<TaskStack> stacks = displayContent.getStacks();
8568        final int numStacks = stacks.size();
8569        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
8570            AppTokenList exitingAppTokens = stacks.get(stackNdx).mExitingAppTokens;
8571            int NT = exitingAppTokens.size();
8572            for (int j = 0; j < NT; j++) {
8573                i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j));
8574            }
8575        }
8576
8577        // And add in the still active app tokens in Z order.
8578        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
8579            final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
8580            final int numTasks = tasks.size();
8581            for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
8582                final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
8583                final int numTokens = tokens.size();
8584                for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
8585                    final AppWindowToken wtoken = tokens.get(tokenNdx);
8586                    if (wtoken.mDeferRemoval) {
8587                        continue;
8588                    }
8589                    i = reAddAppWindowsLocked(displayContent, i, wtoken);
8590                }
8591            }
8592        }
8593
8594        i -= lastBelow;
8595        if (i != numRemoved) {
8596            Slog.w(TAG, "On display=" + displayContent.getDisplayId() + " Rebuild removed " +
8597                    numRemoved + " windows but added " + i,
8598                    new RuntimeException("here").fillInStackTrace());
8599            for (i=0; i<numRemoved; i++) {
8600                WindowState ws = mRebuildTmp[i];
8601                if (ws.mRebuilding) {
8602                    StringWriter sw = new StringWriter();
8603                    PrintWriter pw = new FastPrintWriter(sw, false, 1024);
8604                    ws.dump(pw, "", true);
8605                    pw.flush();
8606                    Slog.w(TAG, "This window was lost: " + ws);
8607                    Slog.w(TAG, sw.toString());
8608                    ws.mWinAnimator.destroySurfaceLocked();
8609                }
8610            }
8611            Slog.w(TAG, "Current app token list:");
8612            dumpAppTokensLocked();
8613            Slog.w(TAG, "Final window list:");
8614            dumpWindowsLocked();
8615        }
8616    }
8617
8618    private final void assignLayersLocked(WindowList windows) {
8619        int N = windows.size();
8620        int curBaseLayer = 0;
8621        int curLayer = 0;
8622        int i;
8623
8624        if (DEBUG_LAYERS) Slog.v(TAG, "Assigning layers based on windows=" + windows,
8625                new RuntimeException("here").fillInStackTrace());
8626
8627        boolean anyLayerChanged = false;
8628
8629        for (i=0; i<N; i++) {
8630            final WindowState w = windows.get(i);
8631            final WindowStateAnimator winAnimator = w.mWinAnimator;
8632            boolean layerChanged = false;
8633            int oldLayer = w.mLayer;
8634            if (w.mBaseLayer == curBaseLayer || w.mIsImWindow
8635                    || (i > 0 && w.mIsWallpaper)) {
8636                curLayer += WINDOW_LAYER_MULTIPLIER;
8637                w.mLayer = curLayer;
8638            } else {
8639                curBaseLayer = curLayer = w.mBaseLayer;
8640                w.mLayer = curLayer;
8641            }
8642            if (w.mLayer != oldLayer) {
8643                layerChanged = true;
8644                anyLayerChanged = true;
8645            }
8646            final AppWindowToken wtoken = w.mAppToken;
8647            oldLayer = winAnimator.mAnimLayer;
8648            if (w.mTargetAppToken != null) {
8649                winAnimator.mAnimLayer =
8650                        w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment;
8651            } else if (wtoken != null) {
8652                winAnimator.mAnimLayer =
8653                        w.mLayer + wtoken.mAppAnimator.animLayerAdjustment;
8654            } else {
8655                winAnimator.mAnimLayer = w.mLayer;
8656            }
8657            if (w.mIsImWindow) {
8658                winAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment;
8659            } else if (w.mIsWallpaper) {
8660                winAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment;
8661            }
8662            if (winAnimator.mAnimLayer != oldLayer) {
8663                layerChanged = true;
8664                anyLayerChanged = true;
8665            }
8666            final TaskStack stack = w.getStack();
8667            if (layerChanged && stack != null && stack.isDimming(winAnimator)) {
8668                // Force an animation pass just to update the mDimLayer layer.
8669                scheduleAnimationLocked();
8670            }
8671            if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": "
8672                    + "mBase=" + w.mBaseLayer
8673                    + " mLayer=" + w.mLayer
8674                    + (wtoken == null ?
8675                            "" : " mAppLayer=" + wtoken.mAppAnimator.animLayerAdjustment)
8676                    + " =mAnimLayer=" + winAnimator.mAnimLayer);
8677            //System.out.println(
8678            //    "Assigned layer " + curLayer + " to " + w.mClient.asBinder());
8679        }
8680
8681        //TODO (multidisplay): Magnification is supported only for the default display.
8682        if (mAccessibilityController != null && anyLayerChanged
8683                && windows.get(windows.size() - 1).getDisplayId() == Display.DEFAULT_DISPLAY) {
8684            mAccessibilityController.onWindowLayersChangedLocked();
8685        }
8686    }
8687
8688    private final void performLayoutAndPlaceSurfacesLocked() {
8689        int loopCount = 6;
8690        do {
8691            mTraversalScheduled = false;
8692            performLayoutAndPlaceSurfacesLockedLoop();
8693            mH.removeMessages(H.DO_TRAVERSAL);
8694            loopCount--;
8695        } while (mTraversalScheduled && loopCount > 0);
8696        mInnerFields.mWallpaperActionPending = false;
8697    }
8698
8699    private boolean mInLayout = false;
8700    private final void performLayoutAndPlaceSurfacesLockedLoop() {
8701        if (mInLayout) {
8702            if (DEBUG) {
8703                throw new RuntimeException("Recursive call!");
8704            }
8705            Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers="
8706                    + Debug.getCallers(3));
8707            return;
8708        }
8709
8710        if (mWaitingForConfig) {
8711            // Our configuration has changed (most likely rotation), but we
8712            // don't yet have the complete configuration to report to
8713            // applications.  Don't do any window layout until we have it.
8714            return;
8715        }
8716
8717        if (!mDisplayReady) {
8718            // Not yet initialized, nothing to do.
8719            return;
8720        }
8721
8722        Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout");
8723        mInLayout = true;
8724        boolean recoveringMemory = false;
8725
8726        try {
8727            if (mForceRemoves != null) {
8728                recoveringMemory = true;
8729                // Wait a little bit for things to settle down, and off we go.
8730                for (int i=0; i<mForceRemoves.size(); i++) {
8731                    WindowState ws = mForceRemoves.get(i);
8732                    Slog.i(TAG, "Force removing: " + ws);
8733                    removeWindowInnerLocked(ws.mSession, ws);
8734                }
8735                mForceRemoves = null;
8736                Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");
8737                Object tmp = new Object();
8738                synchronized (tmp) {
8739                    try {
8740                        tmp.wait(250);
8741                    } catch (InterruptedException e) {
8742                    }
8743                }
8744            }
8745        } catch (RuntimeException e) {
8746            Slog.wtf(TAG, "Unhandled exception while force removing for memory", e);
8747        }
8748
8749        try {
8750            performLayoutAndPlaceSurfacesLockedInner(recoveringMemory);
8751
8752            mInLayout = false;
8753
8754            if (needsLayout()) {
8755                if (++mLayoutRepeatCount < 6) {
8756                    requestTraversalLocked();
8757                } else {
8758                    Slog.e(TAG, "Performed 6 layouts in a row. Skipping");
8759                    mLayoutRepeatCount = 0;
8760                }
8761            } else {
8762                mLayoutRepeatCount = 0;
8763            }
8764
8765            if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) {
8766                mH.removeMessages(H.REPORT_WINDOWS_CHANGE);
8767                mH.sendEmptyMessage(H.REPORT_WINDOWS_CHANGE);
8768            }
8769        } catch (RuntimeException e) {
8770            mInLayout = false;
8771            Slog.wtf(TAG, "Unhandled exception while laying out windows", e);
8772        }
8773
8774        Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
8775    }
8776
8777    private final void performLayoutLockedInner(final DisplayContent displayContent,
8778                                    boolean initial, boolean updateInputWindows) {
8779        if (!displayContent.layoutNeeded) {
8780            return;
8781        }
8782        displayContent.layoutNeeded = false;
8783        WindowList windows = displayContent.getWindowList();
8784        boolean isDefaultDisplay = displayContent.isDefaultDisplay;
8785
8786        DisplayInfo displayInfo = displayContent.getDisplayInfo();
8787        final int dw = displayInfo.logicalWidth;
8788        final int dh = displayInfo.logicalHeight;
8789
8790        final int NFW = mFakeWindows.size();
8791        for (int i=0; i<NFW; i++) {
8792            mFakeWindows.get(i).layout(dw, dh);
8793        }
8794
8795        final int N = windows.size();
8796        int i;
8797
8798        if (DEBUG_LAYOUT) {
8799            Slog.v(TAG, "-------------------------------------");
8800            Slog.v(TAG, "performLayout: needed="
8801                    + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh);
8802        }
8803
8804        WindowStateAnimator universeBackground = null;
8805
8806        mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mRotation);
8807        if (isDefaultDisplay) {
8808            // Not needed on non-default displays.
8809            mSystemDecorLayer = mPolicy.getSystemDecorLayerLw();
8810            mScreenRect.set(0, 0, dw, dh);
8811        }
8812
8813        mPolicy.getContentRectLw(mTmpContentRect);
8814        displayContent.resize(mTmpContentRect);
8815
8816        int seq = mLayoutSeq+1;
8817        if (seq < 0) seq = 0;
8818        mLayoutSeq = seq;
8819
8820        boolean behindDream = false;
8821
8822        // First perform layout of any root windows (not attached
8823        // to another window).
8824        int topAttached = -1;
8825        for (i = N-1; i >= 0; i--) {
8826            final WindowState win = windows.get(i);
8827
8828            // Don't do layout of a window if it is not visible, or
8829            // soon won't be visible, to avoid wasting time and funky
8830            // changes while a window is animating away.
8831            final boolean gone = (behindDream && mPolicy.canBeForceHidden(win, win.mAttrs))
8832                    || win.isGoneForLayoutLw();
8833
8834            if (DEBUG_LAYOUT && !win.mLayoutAttached) {
8835                Slog.v(TAG, "1ST PASS " + win
8836                        + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame
8837                        + " mLayoutAttached=" + win.mLayoutAttached
8838                        + " screen changed=" + win.isConfigChanged());
8839                final AppWindowToken atoken = win.mAppToken;
8840                if (gone) Slog.v(TAG, "  GONE: mViewVisibility="
8841                        + win.mViewVisibility + " mRelayoutCalled="
8842                        + win.mRelayoutCalled + " hidden="
8843                        + win.mRootToken.hidden + " hiddenRequested="
8844                        + (atoken != null && atoken.hiddenRequested)
8845                        + " mAttachedHidden=" + win.mAttachedHidden);
8846                else Slog.v(TAG, "  VIS: mViewVisibility="
8847                        + win.mViewVisibility + " mRelayoutCalled="
8848                        + win.mRelayoutCalled + " hidden="
8849                        + win.mRootToken.hidden + " hiddenRequested="
8850                        + (atoken != null && atoken.hiddenRequested)
8851                        + " mAttachedHidden=" + win.mAttachedHidden);
8852            }
8853
8854            // If this view is GONE, then skip it -- keep the current
8855            // frame, and let the caller know so they can ignore it
8856            // if they want.  (We do the normal layout for INVISIBLE
8857            // windows, since that means "perform layout as normal,
8858            // just don't display").
8859            if (!gone || !win.mHaveFrame || win.mLayoutNeeded
8860                    || ((win.isConfigChanged() || win.setInsetsChanged()) &&
8861                            ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
8862                            win.mAppToken != null && win.mAppToken.layoutConfigChanges))
8863                    || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
8864                if (!win.mLayoutAttached) {
8865                    if (initial) {
8866                        //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
8867                        win.mContentChanged = false;
8868                    }
8869                    if (win.mAttrs.type == TYPE_DREAM) {
8870                        // Don't layout windows behind a dream, so that if it
8871                        // does stuff like hide the status bar we won't get a
8872                        // bad transition when it goes away.
8873                        behindDream = true;
8874                    }
8875                    win.mLayoutNeeded = false;
8876                    win.prelayout();
8877                    mPolicy.layoutWindowLw(win, null);
8878                    win.mLayoutSeq = seq;
8879                    if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame="
8880                            + win.mFrame + " mContainingFrame="
8881                            + win.mContainingFrame + " mDisplayFrame="
8882                            + win.mDisplayFrame);
8883                } else {
8884                    if (topAttached < 0) topAttached = i;
8885                }
8886            }
8887            if (win.mViewVisibility == View.VISIBLE
8888                    && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND
8889                    && universeBackground == null) {
8890                universeBackground = win.mWinAnimator;
8891            }
8892        }
8893
8894        if (mAnimator.mUniverseBackground  != universeBackground) {
8895            mFocusMayChange = true;
8896            mAnimator.mUniverseBackground = universeBackground;
8897        }
8898
8899        boolean attachedBehindDream = false;
8900
8901        // Now perform layout of attached windows, which usually
8902        // depend on the position of the window they are attached to.
8903        // XXX does not deal with windows that are attached to windows
8904        // that are themselves attached.
8905        for (i = topAttached; i >= 0; i--) {
8906            final WindowState win = windows.get(i);
8907
8908            if (win.mLayoutAttached) {
8909                if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win
8910                        + " mHaveFrame=" + win.mHaveFrame
8911                        + " mViewVisibility=" + win.mViewVisibility
8912                        + " mRelayoutCalled=" + win.mRelayoutCalled);
8913                // If this view is GONE, then skip it -- keep the current
8914                // frame, and let the caller know so they can ignore it
8915                // if they want.  (We do the normal layout for INVISIBLE
8916                // windows, since that means "perform layout as normal,
8917                // just don't display").
8918                if (attachedBehindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) {
8919                    continue;
8920                }
8921                if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled)
8922                        || !win.mHaveFrame || win.mLayoutNeeded) {
8923                    if (initial) {
8924                        //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
8925                        win.mContentChanged = false;
8926                    }
8927                    win.mLayoutNeeded = false;
8928                    win.prelayout();
8929                    mPolicy.layoutWindowLw(win, win.mAttachedWindow);
8930                    win.mLayoutSeq = seq;
8931                    if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame="
8932                            + win.mFrame + " mContainingFrame="
8933                            + win.mContainingFrame + " mDisplayFrame="
8934                            + win.mDisplayFrame);
8935                }
8936            } else if (win.mAttrs.type == TYPE_DREAM) {
8937                // Don't layout windows behind a dream, so that if it
8938                // does stuff like hide the status bar we won't get a
8939                // bad transition when it goes away.
8940                attachedBehindDream = behindDream;
8941            }
8942        }
8943
8944        // Window frames may have changed.  Tell the input dispatcher about it.
8945        mInputMonitor.setUpdateInputWindowsNeededLw();
8946        if (updateInputWindows) {
8947            mInputMonitor.updateInputWindowsLw(false /*force*/);
8948        }
8949
8950        mPolicy.finishLayoutLw();
8951    }
8952
8953    void makeWindowFreezingScreenIfNeededLocked(WindowState w) {
8954        // If the screen is currently frozen or off, then keep
8955        // it frozen/off until this window draws at its new
8956        // orientation.
8957        if (!okToDisplay()) {
8958            if (DEBUG_ORIENTATION) Slog.v(TAG, "Changing surface while display frozen: " + w);
8959            w.mOrientationChanging = true;
8960            w.mLastFreezeDuration = 0;
8961            mInnerFields.mOrientationChangeComplete = false;
8962            if (!mWindowsFreezingScreen) {
8963                mWindowsFreezingScreen = true;
8964                // XXX should probably keep timeout from
8965                // when we first froze the display.
8966                mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
8967                mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT,
8968                        WINDOW_FREEZE_TIMEOUT_DURATION);
8969            }
8970        }
8971    }
8972
8973    /**
8974     * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
8975     * @param windows List of windows on default display.
8976     * @return bitmap indicating if another pass through layout must be made.
8977     */
8978    public int handleAppTransitionReadyLocked(WindowList windows) {
8979        int changes = 0;
8980        int i;
8981        int NN = mOpeningApps.size();
8982        boolean goodToGo = true;
8983        if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8984                "Checking " + NN + " opening apps (frozen="
8985                + mDisplayFrozen + " timeout="
8986                + mAppTransition.isTimeout() + ")...");
8987        if (!mDisplayFrozen && !mAppTransition.isTimeout()) {
8988            // If the display isn't frozen, wait to do anything until
8989            // all of the apps are ready.  Otherwise just go because
8990            // we'll unfreeze the display when everyone is ready.
8991            for (i=0; i<NN && goodToGo; i++) {
8992                AppWindowToken wtoken = mOpeningApps.valueAt(i);
8993                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8994                        "Check opening app=" + wtoken + ": allDrawn="
8995                        + wtoken.allDrawn + " startingDisplayed="
8996                        + wtoken.startingDisplayed + " startingMoved="
8997                        + wtoken.startingMoved);
8998                if (!wtoken.allDrawn && !wtoken.startingDisplayed
8999                        && !wtoken.startingMoved) {
9000                    goodToGo = false;
9001                }
9002            }
9003        }
9004        if (goodToGo) {
9005            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO");
9006            int transit = mAppTransition.getAppTransition();
9007            if (mSkipAppTransitionAnimation) {
9008                transit = AppTransition.TRANSIT_UNSET;
9009            }
9010            mAppTransition.goodToGo();
9011            mStartingIconInTransition = false;
9012            mSkipAppTransitionAnimation = false;
9013
9014            mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
9015
9016            rebuildAppWindowListLocked();
9017
9018            // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper
9019            WindowState oldWallpaper =
9020                    mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating()
9021                        && !mWallpaperTarget.mWinAnimator.isDummyAnimation()
9022                    ? null : mWallpaperTarget;
9023
9024            mInnerFields.mWallpaperMayChange = false;
9025
9026            // The top-most window will supply the layout params,
9027            // and we will determine it below.
9028            LayoutParams animLp = null;
9029            int bestAnimLayer = -1;
9030            boolean fullscreenAnim = false;
9031            boolean voiceInteraction = false;
9032
9033            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
9034                    "New wallpaper target=" + mWallpaperTarget
9035                    + ", oldWallpaper=" + oldWallpaper
9036                    + ", lower target=" + mLowerWallpaperTarget
9037                    + ", upper target=" + mUpperWallpaperTarget);
9038
9039            boolean openingAppHasWallpaper = false;
9040            boolean closingAppHasWallpaper = false;
9041            final AppWindowToken lowerWallpaperAppToken;
9042            final AppWindowToken upperWallpaperAppToken;
9043            if (mLowerWallpaperTarget == null) {
9044                lowerWallpaperAppToken = upperWallpaperAppToken = null;
9045            } else {
9046                lowerWallpaperAppToken = mLowerWallpaperTarget.mAppToken;
9047                upperWallpaperAppToken = mUpperWallpaperTarget.mAppToken;
9048            }
9049
9050            // Do a first pass through the tokens for two
9051            // things:
9052            // (1) Determine if both the closing and opening
9053            // app token sets are wallpaper targets, in which
9054            // case special animations are needed
9055            // (since the wallpaper needs to stay static
9056            // behind them).
9057            // (2) Find the layout params of the top-most
9058            // application window in the tokens, which is
9059            // what will control the animation theme.
9060            final int NC = mClosingApps.size();
9061            NN = NC + mOpeningApps.size();
9062            for (i=0; i<NN; i++) {
9063                final AppWindowToken wtoken;
9064                if (i < NC) {
9065                    wtoken = mClosingApps.valueAt(i);
9066                    if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
9067                        closingAppHasWallpaper = true;
9068                    }
9069                } else {
9070                    wtoken = mOpeningApps.valueAt(i - NC);
9071                    if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
9072                        openingAppHasWallpaper = true;
9073                    }
9074                }
9075
9076                voiceInteraction |= wtoken.voiceInteraction;
9077
9078                if (wtoken.appFullscreen) {
9079                    WindowState ws = wtoken.findMainWindow();
9080                    if (ws != null) {
9081                        animLp = ws.mAttrs;
9082                        bestAnimLayer = ws.mLayer;
9083                        fullscreenAnim = true;
9084                    }
9085                } else if (!fullscreenAnim) {
9086                    WindowState ws = wtoken.findMainWindow();
9087                    if (ws != null) {
9088                        if (ws.mLayer > bestAnimLayer) {
9089                            animLp = ws.mAttrs;
9090                            bestAnimLayer = ws.mLayer;
9091                        }
9092                    }
9093                }
9094            }
9095
9096            mAnimateWallpaperWithTarget = false;
9097            if (closingAppHasWallpaper && openingAppHasWallpaper) {
9098                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!");
9099                switch (transit) {
9100                    case AppTransition.TRANSIT_ACTIVITY_OPEN:
9101                    case AppTransition.TRANSIT_TASK_OPEN:
9102                    case AppTransition.TRANSIT_TASK_TO_FRONT:
9103                        transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN;
9104                        break;
9105                    case AppTransition.TRANSIT_ACTIVITY_CLOSE:
9106                    case AppTransition.TRANSIT_TASK_CLOSE:
9107                    case AppTransition.TRANSIT_TASK_TO_BACK:
9108                        transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE;
9109                        break;
9110                }
9111                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit: " + transit);
9112            } else if ((oldWallpaper != null) && !mOpeningApps.isEmpty()
9113                    && !mOpeningApps.contains(oldWallpaper.mAppToken)) {
9114                // We are transitioning from an activity with
9115                // a wallpaper to one without.
9116                transit = AppTransition.TRANSIT_WALLPAPER_CLOSE;
9117                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
9118                        "New transit away from wallpaper: " + transit);
9119            } else if (mWallpaperTarget != null && mWallpaperTarget.isVisibleLw()) {
9120                // We are transitioning from an activity without
9121                // a wallpaper to now showing the wallpaper
9122                transit = AppTransition.TRANSIT_WALLPAPER_OPEN;
9123                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
9124                        "New transit into wallpaper: " + transit);
9125            } else {
9126                mAnimateWallpaperWithTarget = true;
9127            }
9128
9129            // If all closing windows are obscured, then there is
9130            // no need to do an animation.  This is the case, for
9131            // example, when this transition is being done behind
9132            // the lock screen.
9133            if (!mPolicy.allowAppAnimationsLw()) {
9134                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
9135                        "Animations disallowed by keyguard or dream.");
9136                animLp = null;
9137            }
9138
9139            AppWindowToken topOpeningApp = null;
9140            AppWindowToken topClosingApp = null;
9141            int topOpeningLayer = 0;
9142            int topClosingLayer = 0;
9143
9144            // Process all applications animating in place
9145            if (transit == AppTransition.TRANSIT_TASK_IN_PLACE) {
9146                // Find the focused window
9147                final WindowState win =
9148                        findFocusedWindowLocked(getDefaultDisplayContentLocked());
9149                if (win != null) {
9150                    final AppWindowToken wtoken = win.mAppToken;
9151                    final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
9152                    if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now animating app in place " + wtoken);
9153                    appAnimator.clearThumbnail();
9154                    appAnimator.animation = null;
9155                    updateTokenInPlaceLocked(wtoken, transit);
9156                    wtoken.updateReportedVisibilityLocked();
9157
9158                    appAnimator.mAllAppWinAnimators.clear();
9159                    final int N = wtoken.allAppWindows.size();
9160                    for (int j = 0; j < N; j++) {
9161                        appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
9162                    }
9163                    mAnimator.mAnimating |= appAnimator.showAllWindowsLocked();
9164                }
9165            }
9166
9167            NN = mOpeningApps.size();
9168            for (i=0; i<NN; i++) {
9169                AppWindowToken wtoken = mOpeningApps.valueAt(i);
9170                final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
9171                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken);
9172                appAnimator.clearThumbnail();
9173                appAnimator.animation = null;
9174                wtoken.inPendingTransaction = false;
9175                setTokenVisibilityLocked(wtoken, animLp, true, transit, false, voiceInteraction);
9176                wtoken.updateReportedVisibilityLocked();
9177                wtoken.waitingToShow = false;
9178
9179                appAnimator.mAllAppWinAnimators.clear();
9180                final int N = wtoken.allAppWindows.size();
9181                for (int j = 0; j < N; j++) {
9182                    appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
9183                }
9184                mAnimator.mAnimating |= appAnimator.showAllWindowsLocked();
9185
9186                if (animLp != null) {
9187                    int layer = -1;
9188                    for (int j=0; j<wtoken.windows.size(); j++) {
9189                        WindowState win = wtoken.windows.get(j);
9190                        if (win.mWinAnimator.mAnimLayer > layer) {
9191                            layer = win.mWinAnimator.mAnimLayer;
9192                        }
9193                    }
9194                    if (topOpeningApp == null || layer > topOpeningLayer) {
9195                        topOpeningApp = wtoken;
9196                        topOpeningLayer = layer;
9197                    }
9198                }
9199            }
9200            NN = mClosingApps.size();
9201            for (i=0; i<NN; i++) {
9202                AppWindowToken wtoken = mClosingApps.valueAt(i);
9203                final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
9204                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken);
9205                appAnimator.clearThumbnail();
9206                appAnimator.animation = null;
9207                wtoken.inPendingTransaction = false;
9208                setTokenVisibilityLocked(wtoken, animLp, false, transit, false, voiceInteraction);
9209                wtoken.updateReportedVisibilityLocked();
9210                wtoken.waitingToHide = false;
9211                // Force the allDrawn flag, because we want to start
9212                // this guy's animations regardless of whether it's
9213                // gotten drawn.
9214                wtoken.allDrawn = true;
9215                wtoken.deferClearAllDrawn = false;
9216                // Ensure that apps that are mid-starting are also scheduled to have their
9217                // starting windows removed after the animation is complete
9218                if (wtoken.startingWindow != null && !wtoken.startingWindow.mExiting) {
9219                    scheduleRemoveStartingWindowLocked(wtoken);
9220                }
9221
9222                if (animLp != null) {
9223                    int layer = -1;
9224                    for (int j=0; j<wtoken.windows.size(); j++) {
9225                        WindowState win = wtoken.windows.get(j);
9226                        if (win.mWinAnimator.mAnimLayer > layer) {
9227                            layer = win.mWinAnimator.mAnimLayer;
9228                        }
9229                    }
9230                    if (topClosingApp == null || layer > topClosingLayer) {
9231                        topClosingApp = wtoken;
9232                        topClosingLayer = layer;
9233                    }
9234                }
9235            }
9236
9237            AppWindowAnimator openingAppAnimator = (topOpeningApp == null) ? null :
9238                    topOpeningApp.mAppAnimator;
9239            AppWindowAnimator closingAppAnimator = (topClosingApp == null) ? null :
9240                    topClosingApp.mAppAnimator;
9241            Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail();
9242            if (nextAppTransitionThumbnail != null
9243                    && openingAppAnimator != null && openingAppAnimator.animation != null &&
9244                    nextAppTransitionThumbnail.getConfig() != Config.ALPHA_8) {
9245                // This thumbnail animation is very special, we need to have
9246                // an extra surface with the thumbnail included with the animation.
9247                Rect dirty = new Rect(0, 0, nextAppTransitionThumbnail.getWidth(),
9248                        nextAppTransitionThumbnail.getHeight());
9249                try {
9250                    // TODO(multi-display): support other displays
9251                    final DisplayContent displayContent = getDefaultDisplayContentLocked();
9252                    final Display display = displayContent.getDisplay();
9253                    final DisplayInfo displayInfo = displayContent.getDisplayInfo();
9254
9255                    // Create a new surface for the thumbnail
9256                    SurfaceControl surfaceControl = new SurfaceControl(mFxSession,
9257                            "thumbnail anim", dirty.width(), dirty.height(),
9258                            PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
9259                    surfaceControl.setLayerStack(display.getLayerStack());
9260                    if (SHOW_TRANSACTIONS) {
9261                        Slog.i(TAG, "  THUMBNAIL " + surfaceControl + ": CREATE");
9262                    }
9263
9264                    // Draw the thumbnail onto the surface
9265                    Surface drawSurface = new Surface();
9266                    drawSurface.copyFrom(surfaceControl);
9267                    Canvas c = drawSurface.lockCanvas(dirty);
9268                    c.drawBitmap(nextAppTransitionThumbnail, 0, 0, null);
9269                    drawSurface.unlockCanvasAndPost(c);
9270                    drawSurface.release();
9271
9272                    // Get the thumbnail animation
9273                    Animation anim;
9274                    if (mAppTransition.isNextThumbnailTransitionAspectScaled()) {
9275                        // For the new aspect-scaled transition, we want it to always show
9276                        // above the animating opening/closing window, and we want to
9277                        // synchronize its thumbnail surface with the surface for the
9278                        // open/close animation (only on the way down)
9279                        anim = mAppTransition.createThumbnailAspectScaleAnimationLocked(
9280                                displayInfo.appWidth, displayInfo.appHeight,
9281                                displayInfo.logicalWidth, transit);
9282                        openingAppAnimator.thumbnailForceAboveLayer = Math.max(topOpeningLayer,
9283                                topClosingLayer);
9284                        openingAppAnimator.deferThumbnailDestruction =
9285                                !mAppTransition.isNextThumbnailTransitionScaleUp();
9286                    } else {
9287                        anim = mAppTransition.createThumbnailScaleAnimationLocked(
9288                                displayInfo.appWidth, displayInfo.appHeight, transit);
9289                    }
9290                    anim.restrictDuration(MAX_ANIMATION_DURATION);
9291                    anim.scaleCurrentDuration(getTransitionAnimationScaleLocked());
9292
9293                    openingAppAnimator.thumbnail = surfaceControl;
9294                    openingAppAnimator.thumbnailLayer = topOpeningLayer;
9295                    openingAppAnimator.thumbnailAnimation = anim;
9296                    openingAppAnimator.thumbnailX = mAppTransition.getStartingX();
9297                    openingAppAnimator.thumbnailY = mAppTransition.getStartingY();
9298                } catch (OutOfResourcesException e) {
9299                    Slog.e(TAG, "Can't allocate thumbnail/Canvas surface w=" + dirty.width()
9300                            + " h=" + dirty.height(), e);
9301                    openingAppAnimator.clearThumbnail();
9302                }
9303            }
9304
9305            mAppTransition.postAnimationCallback();
9306            mAppTransition.clear();
9307
9308            mOpeningApps.clear();
9309            mClosingApps.clear();
9310
9311            // This has changed the visibility of windows, so perform
9312            // a new layout to get them all up-to-date.
9313            changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT
9314                    | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
9315            getDefaultDisplayContentLocked().layoutNeeded = true;
9316
9317            // TODO(multidisplay): IMEs are only supported on the default display.
9318            if (windows == getDefaultWindowListLocked()
9319                    && !moveInputMethodWindowsIfNeededLocked(true)) {
9320                assignLayersLocked(windows);
9321            }
9322            updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, true /*updateInputWindows*/);
9323            mFocusMayChange = false;
9324            notifyActivityDrawnForKeyguard();
9325        }
9326
9327        return changes;
9328    }
9329
9330    /**
9331     * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
9332     * @return bitmap indicating if another pass through layout must be made.
9333     */
9334    private int handleAnimatingStoppedAndTransitionLocked() {
9335        int changes = 0;
9336
9337        mAppTransition.setIdle();
9338        // Restore window app tokens to the ActivityManager views
9339        ArrayList<TaskStack> stacks = getDefaultDisplayContentLocked().getStacks();
9340        for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
9341            final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
9342            for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
9343                final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
9344                for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
9345                    tokens.get(tokenNdx).sendingToBottom = false;
9346                }
9347            }
9348        }
9349        rebuildAppWindowListLocked();
9350
9351        changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
9352        if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
9353                "Wallpaper layer changed: assigning layers + relayout");
9354        moveInputMethodWindowsIfNeededLocked(true);
9355        mInnerFields.mWallpaperMayChange = true;
9356        // Since the window list has been rebuilt, focus might
9357        // have to be recomputed since the actual order of windows
9358        // might have changed again.
9359        mFocusMayChange = true;
9360
9361        return changes;
9362    }
9363
9364    private void updateResizingWindows(final WindowState w) {
9365        final WindowStateAnimator winAnimator = w.mWinAnimator;
9366        if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq) {
9367            w.setInsetsChanged();
9368            boolean configChanged = w.isConfigChanged();
9369            if (DEBUG_CONFIGURATION && configChanged) {
9370                Slog.v(TAG, "Win " + w + " config changed: "
9371                        + mCurConfiguration);
9372            }
9373            if (localLOGV) Slog.v(TAG, "Resizing " + w
9374                    + ": configChanged=" + configChanged
9375                    + " last=" + w.mLastFrame + " frame=" + w.mFrame);
9376            w.mLastFrame.set(w.mFrame);
9377            if (w.mContentInsetsChanged
9378                    || w.mVisibleInsetsChanged
9379                    || winAnimator.mSurfaceResized
9380                    || configChanged) {
9381                if (DEBUG_RESIZE || DEBUG_ORIENTATION) {
9382                    Slog.v(TAG, "Resize reasons for w=" + w + ": "
9383                            + " contentInsetsChanged=" + w.mContentInsetsChanged
9384                            + " " + w.mContentInsets.toShortString()
9385                            + " visibleInsetsChanged=" + w.mVisibleInsetsChanged
9386                            + " " + w.mVisibleInsets.toShortString()
9387                            + " stableInsetsChanged=" + w.mStableInsetsChanged
9388                            + " " + w.mStableInsets.toShortString()
9389                            + " surfaceResized=" + winAnimator.mSurfaceResized
9390                            + " configChanged=" + configChanged);
9391                }
9392
9393                w.mLastOverscanInsets.set(w.mOverscanInsets);
9394                w.mLastContentInsets.set(w.mContentInsets);
9395                w.mLastVisibleInsets.set(w.mVisibleInsets);
9396                w.mLastStableInsets.set(w.mStableInsets);
9397                makeWindowFreezingScreenIfNeededLocked(w);
9398                // If the orientation is changing, then we need to
9399                // hold off on unfreezing the display until this
9400                // window has been redrawn; to do that, we need
9401                // to go through the process of getting informed
9402                // by the application when it has finished drawing.
9403                if (w.mOrientationChanging) {
9404                    if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION) Slog.v(TAG,
9405                            "Orientation start waiting for draw mDrawState=DRAW_PENDING in "
9406                            + w + ", surface " + winAnimator.mSurfaceControl);
9407                    winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
9408                    if (w.mAppToken != null) {
9409                        w.mAppToken.allDrawn = false;
9410                        w.mAppToken.deferClearAllDrawn = false;
9411                    }
9412                }
9413                if (!mResizingWindows.contains(w)) {
9414                    if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
9415                            "Resizing window " + w + " to " + winAnimator.mSurfaceW
9416                            + "x" + winAnimator.mSurfaceH);
9417                    mResizingWindows.add(w);
9418                }
9419            } else if (w.mOrientationChanging) {
9420                if (w.isDrawnLw()) {
9421                    if (DEBUG_ORIENTATION) Slog.v(TAG,
9422                            "Orientation not waiting for draw in "
9423                            + w + ", surface " + winAnimator.mSurfaceControl);
9424                    w.mOrientationChanging = false;
9425                    w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
9426                            - mDisplayFreezeTime);
9427                }
9428            }
9429        }
9430    }
9431
9432    /**
9433     * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
9434     *
9435     * @param w WindowState this method is applied to.
9436     * @param currentTime The time which animations use for calculating transitions.
9437     * @param innerDw Width of app window.
9438     * @param innerDh Height of app window.
9439     */
9440    private void handleNotObscuredLocked(final WindowState w, final long currentTime,
9441                                         final int innerDw, final int innerDh) {
9442        final WindowManager.LayoutParams attrs = w.mAttrs;
9443        final int attrFlags = attrs.flags;
9444        final boolean canBeSeen = w.isDisplayedLw();
9445        final boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn();
9446
9447        if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) {
9448            // This window completely covers everything behind it,
9449            // so we want to leave all of them as undimmed (for
9450            // performance reasons).
9451            mInnerFields.mObscured = true;
9452        }
9453
9454        if (w.mHasSurface) {
9455            if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) {
9456                mInnerFields.mHoldScreen = w.mSession;
9457            }
9458            if (!mInnerFields.mSyswin && w.mAttrs.screenBrightness >= 0
9459                    && mInnerFields.mScreenBrightness < 0) {
9460                mInnerFields.mScreenBrightness = w.mAttrs.screenBrightness;
9461            }
9462            if (!mInnerFields.mSyswin && w.mAttrs.buttonBrightness >= 0
9463                    && mInnerFields.mButtonBrightness < 0) {
9464                mInnerFields.mButtonBrightness = w.mAttrs.buttonBrightness;
9465            }
9466            if (!mInnerFields.mSyswin && w.mAttrs.userActivityTimeout >= 0
9467                    && mInnerFields.mUserActivityTimeout < 0) {
9468                mInnerFields.mUserActivityTimeout = w.mAttrs.userActivityTimeout;
9469            }
9470
9471            final int type = attrs.type;
9472            if (canBeSeen
9473                    && (type == TYPE_SYSTEM_DIALOG
9474                     || type == TYPE_SYSTEM_ERROR
9475                     || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0)) {
9476                mInnerFields.mSyswin = true;
9477            }
9478
9479            if (canBeSeen) {
9480                // This function assumes that the contents of the default display are
9481                // processed first before secondary displays.
9482                final DisplayContent displayContent = w.getDisplayContent();
9483                if (displayContent != null && displayContent.isDefaultDisplay) {
9484                    // While a dream or keyguard is showing, obscure ordinary application
9485                    // content on secondary displays (by forcibly enabling mirroring unless
9486                    // there is other content we want to show) but still allow opaque
9487                    // keyguard dialogs to be shown.
9488                    if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
9489                        mInnerFields.mObscureApplicationContentOnSecondaryDisplays = true;
9490                    }
9491                    mInnerFields.mDisplayHasContent = true;
9492                } else if (displayContent != null &&
9493                        (!mInnerFields.mObscureApplicationContentOnSecondaryDisplays
9494                        || (mInnerFields.mObscured && type == TYPE_KEYGUARD_DIALOG))) {
9495                    // Allow full screen keyguard presentation dialogs to be seen.
9496                    mInnerFields.mDisplayHasContent = true;
9497                }
9498                if (mInnerFields.mPreferredRefreshRate == 0
9499                        && w.mAttrs.preferredRefreshRate != 0) {
9500                    mInnerFields.mPreferredRefreshRate = w.mAttrs.preferredRefreshRate;
9501                }
9502            }
9503        }
9504    }
9505
9506    private void handleFlagDimBehind(WindowState w) {
9507        final WindowManager.LayoutParams attrs = w.mAttrs;
9508        if ((attrs.flags & FLAG_DIM_BEHIND) != 0
9509                && w.isDisplayedLw()
9510                && !w.mExiting) {
9511            final WindowStateAnimator winAnimator = w.mWinAnimator;
9512            final TaskStack stack = w.getStack();
9513            if (stack == null) {
9514                return;
9515            }
9516            stack.setDimmingTag();
9517            if (!stack.isDimming(winAnimator)) {
9518                if (localLOGV) Slog.v(TAG, "Win " + w + " start dimming.");
9519                stack.startDimmingIfNeeded(winAnimator);
9520            }
9521        }
9522    }
9523
9524    private void updateAllDrawnLocked(DisplayContent displayContent) {
9525        // See if any windows have been drawn, so they (and others
9526        // associated with them) can now be shown.
9527        ArrayList<TaskStack> stacks = displayContent.getStacks();
9528        for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
9529            final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
9530            for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
9531                final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
9532                for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
9533                    final AppWindowToken wtoken = tokens.get(tokenNdx);
9534                    if (!wtoken.allDrawn) {
9535                        int numInteresting = wtoken.numInterestingWindows;
9536                        if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
9537                            if (DEBUG_VISIBILITY) Slog.v(TAG,
9538                                    "allDrawn: " + wtoken
9539                                    + " interesting=" + numInteresting
9540                                    + " drawn=" + wtoken.numDrawnWindows);
9541                            wtoken.allDrawn = true;
9542                            // Force an additional layout pass where WindowStateAnimator#
9543                            // commitFinishDrawingLocked() will call performShowLocked().
9544                            displayContent.layoutNeeded = true;
9545                            mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, wtoken.token).sendToTarget();
9546                        }
9547                    }
9548                }
9549            }
9550        }
9551    }
9552
9553    // "Something has changed!  Let's make it correct now."
9554    private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) {
9555        if (DEBUG_WINDOW_TRACE) {
9556            Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by "
9557                    + Debug.getCallers(3));
9558        }
9559
9560        final long currentTime = SystemClock.uptimeMillis();
9561
9562        int i;
9563        boolean updateInputWindowsNeeded = false;
9564
9565        if (mFocusMayChange) {
9566            mFocusMayChange = false;
9567            updateInputWindowsNeeded = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
9568                    false /*updateInputWindows*/);
9569        }
9570
9571        // Initialize state of exiting tokens.
9572        final int numDisplays = mDisplayContents.size();
9573        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9574            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9575            for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) {
9576                displayContent.mExitingTokens.get(i).hasVisible = false;
9577            }
9578        }
9579
9580        for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
9581            // Initialize state of exiting applications.
9582            final AppTokenList exitingAppTokens =
9583                    mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
9584            for (int tokenNdx = exitingAppTokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
9585                exitingAppTokens.get(tokenNdx).hasVisible = false;
9586            }
9587        }
9588
9589        mInnerFields.mHoldScreen = null;
9590        mInnerFields.mScreenBrightness = -1;
9591        mInnerFields.mButtonBrightness = -1;
9592        mInnerFields.mUserActivityTimeout = -1;
9593        mInnerFields.mObscureApplicationContentOnSecondaryDisplays = false;
9594
9595        mTransactionSequence++;
9596
9597        final DisplayContent defaultDisplay = getDefaultDisplayContentLocked();
9598        final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo();
9599        final int defaultDw = defaultInfo.logicalWidth;
9600        final int defaultDh = defaultInfo.logicalHeight;
9601
9602        if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
9603                ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
9604        SurfaceControl.openTransaction();
9605        try {
9606
9607            if (mWatermark != null) {
9608                mWatermark.positionSurface(defaultDw, defaultDh);
9609            }
9610            if (mStrictModeFlash != null) {
9611                mStrictModeFlash.positionSurface(defaultDw, defaultDh);
9612            }
9613            if (mCircularDisplayMask != null) {
9614                mCircularDisplayMask.positionSurface(defaultDw, defaultDh, mRotation);
9615            }
9616            if (mEmulatorDisplayOverlay != null) {
9617                mEmulatorDisplayOverlay.positionSurface(defaultDw, defaultDh, mRotation);
9618            }
9619
9620            boolean focusDisplayed = false;
9621
9622            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9623                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9624                boolean updateAllDrawn = false;
9625                WindowList windows = displayContent.getWindowList();
9626                DisplayInfo displayInfo = displayContent.getDisplayInfo();
9627                final int displayId = displayContent.getDisplayId();
9628                final int dw = displayInfo.logicalWidth;
9629                final int dh = displayInfo.logicalHeight;
9630                final int innerDw = displayInfo.appWidth;
9631                final int innerDh = displayInfo.appHeight;
9632                final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
9633
9634                // Reset for each display.
9635                mInnerFields.mDisplayHasContent = false;
9636                mInnerFields.mPreferredRefreshRate = 0;
9637
9638                int repeats = 0;
9639                do {
9640                    repeats++;
9641                    if (repeats > 6) {
9642                        Slog.w(TAG, "Animation repeat aborted after too many iterations");
9643                        displayContent.layoutNeeded = false;
9644                        break;
9645                    }
9646
9647                    if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner",
9648                        displayContent.pendingLayoutChanges);
9649
9650                    if ((displayContent.pendingLayoutChanges &
9651                            WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0 &&
9652                            (adjustWallpaperWindowsLocked() &
9653                                    ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
9654                        assignLayersLocked(windows);
9655                        displayContent.layoutNeeded = true;
9656                    }
9657
9658                    if (isDefaultDisplay && (displayContent.pendingLayoutChanges
9659                            & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
9660                        if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
9661                        if (updateOrientationFromAppTokensLocked(true)) {
9662                            displayContent.layoutNeeded = true;
9663                            mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
9664                        }
9665                    }
9666
9667                    if ((displayContent.pendingLayoutChanges
9668                            & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
9669                        displayContent.layoutNeeded = true;
9670                    }
9671
9672                    // FIRST LOOP: Perform a layout, if needed.
9673                    if (repeats < 4) {
9674                        performLayoutLockedInner(displayContent, repeats == 1,
9675                                false /*updateInputWindows*/);
9676                    } else {
9677                        Slog.w(TAG, "Layout repeat skipped after too many iterations");
9678                    }
9679
9680                    // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think
9681                    // it is animating.
9682                    displayContent.pendingLayoutChanges = 0;
9683
9684                    if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number "
9685                            + mLayoutRepeatCount, displayContent.pendingLayoutChanges);
9686
9687                    if (isDefaultDisplay) {
9688                        mPolicy.beginPostLayoutPolicyLw(dw, dh);
9689                        for (i = windows.size() - 1; i >= 0; i--) {
9690                            WindowState w = windows.get(i);
9691                            if (w.mHasSurface) {
9692                                mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs, w.mAttachedWindow);
9693                            }
9694                        }
9695                        displayContent.pendingLayoutChanges |= mPolicy.finishPostLayoutPolicyLw();
9696                        if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats(
9697                            "after finishPostLayoutPolicyLw", displayContent.pendingLayoutChanges);
9698                    }
9699                } while (displayContent.pendingLayoutChanges != 0);
9700
9701                mInnerFields.mObscured = false;
9702                mInnerFields.mSyswin = false;
9703                displayContent.resetDimming();
9704
9705                // Only used if default window
9706                final boolean someoneLosingFocus = !mLosingFocus.isEmpty();
9707
9708                final int N = windows.size();
9709                for (i=N-1; i>=0; i--) {
9710                    WindowState w = windows.get(i);
9711                    final TaskStack stack = w.getStack();
9712                    if (stack == null && w.getAttrs().type != TYPE_PRIVATE_PRESENTATION) {
9713                        continue;
9714                    }
9715
9716                    final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured;
9717
9718                    // Update effect.
9719                    w.mObscured = mInnerFields.mObscured;
9720                    if (!mInnerFields.mObscured) {
9721                        handleNotObscuredLocked(w, currentTime, innerDw, innerDh);
9722                    }
9723
9724                    if (stack != null && !stack.testDimmingTag()) {
9725                        handleFlagDimBehind(w);
9726                    }
9727
9728                    if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w)
9729                            && w.isVisibleLw()) {
9730                        // This is the wallpaper target and its obscured state
9731                        // changed... make sure the current wallaper's visibility
9732                        // has been updated accordingly.
9733                        updateWallpaperVisibilityLocked();
9734                    }
9735
9736                    final WindowStateAnimator winAnimator = w.mWinAnimator;
9737
9738                    // If the window has moved due to its containing
9739                    // content frame changing, then we'd like to animate
9740                    // it.
9741                    if (w.mHasSurface && w.shouldAnimateMove()) {
9742                        // Frame has moved, containing content frame
9743                        // has also moved, and we're not currently animating...
9744                        // let's do something.
9745                        Animation a = AnimationUtils.loadAnimation(mContext,
9746                                com.android.internal.R.anim.window_move_from_decor);
9747                        winAnimator.setAnimation(a);
9748                        winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left;
9749                        winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top;
9750
9751                        //TODO (multidisplay): Accessibility supported only for the default display.
9752                        if (mAccessibilityController != null
9753                                && displayId == Display.DEFAULT_DISPLAY) {
9754                            mAccessibilityController.onSomeWindowResizedOrMovedLocked();
9755                        }
9756
9757                        try {
9758                            w.mClient.moved(w.mFrame.left, w.mFrame.top);
9759                        } catch (RemoteException e) {
9760                        }
9761                    }
9762
9763                    //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
9764                    w.mContentChanged = false;
9765
9766                    // Moved from updateWindowsAndWallpaperLocked().
9767                    if (w.mHasSurface && !w.isHiddenFromUserLocked()) {
9768                        // Take care of the window being ready to display.
9769                        final boolean committed =
9770                                winAnimator.commitFinishDrawingLocked(currentTime);
9771                        if (isDefaultDisplay && committed) {
9772                            if (w.mAttrs.type == TYPE_DREAM) {
9773                                // HACK: When a dream is shown, it may at that
9774                                // point hide the lock screen.  So we need to
9775                                // redo the layout to let the phone window manager
9776                                // make this happen.
9777                                displayContent.pendingLayoutChanges |=
9778                                        WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9779                                if (DEBUG_LAYOUT_REPEATS) {
9780                                    debugLayoutRepeats(
9781                                        "dream and commitFinishDrawingLocked true",
9782                                        displayContent.pendingLayoutChanges);
9783                                }
9784                            }
9785                            if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
9786                                if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
9787                                        "First draw done in potential wallpaper target " + w);
9788                                mInnerFields.mWallpaperMayChange = true;
9789                                displayContent.pendingLayoutChanges |=
9790                                        WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
9791                                if (DEBUG_LAYOUT_REPEATS) {
9792                                    debugLayoutRepeats(
9793                                        "wallpaper and commitFinishDrawingLocked true",
9794                                        displayContent.pendingLayoutChanges);
9795                                }
9796                            }
9797                        }
9798
9799                        winAnimator.setSurfaceBoundariesLocked(recoveringMemory);
9800
9801                        final AppWindowToken atoken = w.mAppToken;
9802                        if (DEBUG_STARTING_WINDOW && atoken != null
9803                                && w == atoken.startingWindow) {
9804                            Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen="
9805                                + w.isOnScreen() + " allDrawn=" + atoken.allDrawn
9806                                + " freezingScreen=" + atoken.mAppAnimator.freezingScreen);
9807                        }
9808                        if (atoken != null
9809                                && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) {
9810                            if (atoken.lastTransactionSequence != mTransactionSequence) {
9811                                atoken.lastTransactionSequence = mTransactionSequence;
9812                                atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
9813                                atoken.startingDisplayed = false;
9814                            }
9815                            if ((w.isOnScreenIgnoringKeyguard()
9816                                    || winAnimator.mAttrType == TYPE_BASE_APPLICATION)
9817                                    && !w.mExiting && !w.mDestroying) {
9818                                if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
9819                                    Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
9820                                            + ", isAnimating=" + winAnimator.isAnimating());
9821                                    if (!w.isDrawnLw()) {
9822                                        Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceControl
9823                                                + " pv=" + w.mPolicyVisibility
9824                                                + " mDrawState=" + winAnimator.drawStateToString()
9825                                                + " ah=" + w.mAttachedHidden
9826                                                + " th=" + atoken.hiddenRequested
9827                                                + " a=" + winAnimator.mAnimating);
9828                                    }
9829                                }
9830                                if (w != atoken.startingWindow) {
9831                                    if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) {
9832                                        atoken.numInterestingWindows++;
9833                                        if (w.isDrawnLw()) {
9834                                            atoken.numDrawnWindows++;
9835                                            if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG,
9836                                                    "tokenMayBeDrawn: " + atoken
9837                                                    + " freezingScreen=" + atoken.mAppAnimator.freezingScreen
9838                                                    + " mAppFreezing=" + w.mAppFreezing);
9839                                            updateAllDrawn = true;
9840                                        }
9841                                    }
9842                                } else if (w.isDrawnLw()) {
9843                                    atoken.startingDisplayed = true;
9844                                }
9845                            }
9846                        }
9847                    }
9848
9849                    if (isDefaultDisplay && someoneLosingFocus && (w == mCurrentFocus)
9850                            && w.isDisplayedLw()) {
9851                        focusDisplayed = true;
9852                    }
9853
9854                    updateResizingWindows(w);
9855                }
9856
9857                mDisplayManagerInternal.setDisplayProperties(displayId,
9858                        mInnerFields.mDisplayHasContent, mInnerFields.mPreferredRefreshRate,
9859                        true /* inTraversal, must call performTraversalInTrans... below */);
9860
9861                getDisplayContentLocked(displayId).stopDimmingIfNeeded();
9862
9863                if (updateAllDrawn) {
9864                    updateAllDrawnLocked(displayContent);
9865                }
9866            }
9867
9868            if (focusDisplayed) {
9869                mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS);
9870            }
9871
9872            // Give the display manager a chance to adjust properties
9873            // like display rotation if it needs to.
9874            mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
9875
9876        } catch (RuntimeException e) {
9877            Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
9878        } finally {
9879            SurfaceControl.closeTransaction();
9880            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
9881                    "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
9882        }
9883
9884        final WindowList defaultWindows = defaultDisplay.getWindowList();
9885
9886        // If we are ready to perform an app transition, check through
9887        // all of the app tokens to be shown and see if they are ready
9888        // to go.
9889        if (mAppTransition.isReady()) {
9890            defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows);
9891            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked",
9892                    defaultDisplay.pendingLayoutChanges);
9893        }
9894
9895        if (!mAnimator.mAnimating && mAppTransition.isRunning()) {
9896            // We have finished the animation of an app transition.  To do
9897            // this, we have delayed a lot of operations like showing and
9898            // hiding apps, moving apps in Z-order, etc.  The app token list
9899            // reflects the correct Z-order, but the window list may now
9900            // be out of sync with it.  So here we will just rebuild the
9901            // entire app window list.  Fun!
9902            defaultDisplay.pendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked();
9903            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock",
9904                defaultDisplay.pendingLayoutChanges);
9905        }
9906
9907        if (mInnerFields.mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0
9908                && !mAppTransition.isReady()) {
9909            // At this point, there was a window with a wallpaper that
9910            // was force hiding other windows behind it, but now it
9911            // is going away.  This may be simple -- just animate
9912            // away the wallpaper and its window -- or it may be
9913            // hard -- the wallpaper now needs to be shown behind
9914            // something that was hidden.
9915            defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9916            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked",
9917                defaultDisplay.pendingLayoutChanges);
9918        }
9919        mInnerFields.mWallpaperForceHidingChanged = false;
9920
9921        if (mInnerFields.mWallpaperMayChange) {
9922            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Wallpaper may change!  Adjusting");
9923            defaultDisplay.pendingLayoutChanges |=
9924                    WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
9925            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("WallpaperMayChange",
9926                    defaultDisplay.pendingLayoutChanges);
9927        }
9928
9929        if (mFocusMayChange) {
9930            mFocusMayChange = false;
9931            if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
9932                    false /*updateInputWindows*/)) {
9933                updateInputWindowsNeeded = true;
9934                defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
9935            }
9936        }
9937
9938        if (needsLayout()) {
9939            defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9940            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded",
9941                    defaultDisplay.pendingLayoutChanges);
9942        }
9943
9944        for (i = mResizingWindows.size() - 1; i >= 0; i--) {
9945            WindowState win = mResizingWindows.get(i);
9946            if (win.mAppFreezing) {
9947                // Don't remove this window until rotation has completed.
9948                continue;
9949            }
9950            win.reportResized();
9951            mResizingWindows.remove(i);
9952        }
9953
9954        if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG,
9955                "With display frozen, orientationChangeComplete="
9956                + mInnerFields.mOrientationChangeComplete);
9957        if (mInnerFields.mOrientationChangeComplete) {
9958            if (mWindowsFreezingScreen) {
9959                mWindowsFreezingScreen = false;
9960                mLastFinishedFreezeSource = mInnerFields.mLastWindowFreezeSource;
9961                mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
9962            }
9963            stopFreezingDisplayLocked();
9964        }
9965
9966        // Destroy the surface of any windows that are no longer visible.
9967        boolean wallpaperDestroyed = false;
9968        i = mDestroySurface.size();
9969        if (i > 0) {
9970            do {
9971                i--;
9972                WindowState win = mDestroySurface.get(i);
9973                win.mDestroying = false;
9974                if (mInputMethodWindow == win) {
9975                    mInputMethodWindow = null;
9976                }
9977                if (win == mWallpaperTarget) {
9978                    wallpaperDestroyed = true;
9979                }
9980                win.mWinAnimator.destroySurfaceLocked();
9981            } while (i > 0);
9982            mDestroySurface.clear();
9983        }
9984
9985        // Time to remove any exiting tokens?
9986        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9987            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9988            ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens;
9989            for (i = exitingTokens.size() - 1; i >= 0; i--) {
9990                WindowToken token = exitingTokens.get(i);
9991                if (!token.hasVisible) {
9992                    exitingTokens.remove(i);
9993                    if (token.windowType == TYPE_WALLPAPER) {
9994                        mWallpaperTokens.remove(token);
9995                    }
9996                }
9997            }
9998        }
9999
10000        // Time to remove any exiting applications?
10001        for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
10002            // Initialize state of exiting applications.
10003            final AppTokenList exitingAppTokens =
10004                    mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
10005            for (i = exitingAppTokens.size() - 1; i >= 0; i--) {
10006                AppWindowToken token = exitingAppTokens.get(i);
10007                if (!token.hasVisible && !mClosingApps.contains(token) && !token.mDeferRemoval) {
10008                    // Make sure there is no animation running on this token,
10009                    // so any windows associated with it will be removed as
10010                    // soon as their animations are complete
10011                    token.mAppAnimator.clearAnimation();
10012                    token.mAppAnimator.animating = false;
10013                    if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
10014                            "performLayout: App token exiting now removed" + token);
10015                    removeAppFromTaskLocked(token);
10016                    exitingAppTokens.remove(i);
10017                }
10018            }
10019        }
10020
10021        if (!mAnimator.mAnimating && mRelayoutWhileAnimating.size() > 0) {
10022            for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) {
10023                try {
10024                    mRelayoutWhileAnimating.get(j).mClient.doneAnimating();
10025                } catch (RemoteException e) {
10026                }
10027            }
10028            mRelayoutWhileAnimating.clear();
10029        }
10030
10031        if (wallpaperDestroyed) {
10032            defaultDisplay.pendingLayoutChanges |=
10033                    WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
10034            defaultDisplay.layoutNeeded = true;
10035        }
10036
10037        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10038            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
10039            if (displayContent.pendingLayoutChanges != 0) {
10040                displayContent.layoutNeeded = true;
10041            }
10042        }
10043
10044        // Finally update all input windows now that the window changes have stabilized.
10045        mInputMonitor.updateInputWindowsLw(true /*force*/);
10046
10047        setHoldScreenLocked(mInnerFields.mHoldScreen);
10048        if (!mDisplayFrozen) {
10049            if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) {
10050                mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(-1);
10051            } else {
10052                mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(
10053                        toBrightnessOverride(mInnerFields.mScreenBrightness));
10054            }
10055            if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) {
10056                mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(-1);
10057            } else {
10058                mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(
10059                        toBrightnessOverride(mInnerFields.mButtonBrightness));
10060            }
10061            mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager(
10062                    mInnerFields.mUserActivityTimeout);
10063        }
10064
10065        if (mTurnOnScreen) {
10066            if (mAllowTheaterModeWakeFromLayout
10067                    || Settings.Global.getInt(mContext.getContentResolver(),
10068                        Settings.Global.THEATER_MODE_ON, 0) == 0) {
10069                if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!");
10070                mPowerManager.wakeUp(SystemClock.uptimeMillis());
10071            }
10072            mTurnOnScreen = false;
10073        }
10074
10075        if (mInnerFields.mUpdateRotation) {
10076            if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
10077            if (updateRotationUncheckedLocked(false)) {
10078                mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
10079            } else {
10080                mInnerFields.mUpdateRotation = false;
10081            }
10082        }
10083
10084        if (mWaitingForDrawnCallback != null ||
10085                (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded &&
10086                        !mInnerFields.mUpdateRotation)) {
10087            checkDrawnWindowsLocked();
10088        }
10089
10090        final int N = mPendingRemove.size();
10091        if (N > 0) {
10092            if (mPendingRemoveTmp.length < N) {
10093                mPendingRemoveTmp = new WindowState[N+10];
10094            }
10095            mPendingRemove.toArray(mPendingRemoveTmp);
10096            mPendingRemove.clear();
10097            DisplayContentList displayList = new DisplayContentList();
10098            for (i = 0; i < N; i++) {
10099                WindowState w = mPendingRemoveTmp[i];
10100                removeWindowInnerLocked(w.mSession, w);
10101                final DisplayContent displayContent = w.getDisplayContent();
10102                if (displayContent != null && !displayList.contains(displayContent)) {
10103                    displayList.add(displayContent);
10104                }
10105            }
10106
10107            for (DisplayContent displayContent : displayList) {
10108                assignLayersLocked(displayContent.getWindowList());
10109                displayContent.layoutNeeded = true;
10110            }
10111        }
10112
10113        // Remove all deferred displays stacks, tasks, and activities.
10114        for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
10115            mDisplayContents.valueAt(displayNdx).checkForDeferredActions();
10116        }
10117
10118        if (updateInputWindowsNeeded) {
10119            mInputMonitor.updateInputWindowsLw(false /*force*/);
10120        }
10121        setFocusedStackFrame();
10122
10123        // Check to see if we are now in a state where the screen should
10124        // be enabled, because the window obscured flags have changed.
10125        enableScreenIfNeededLocked();
10126
10127        scheduleAnimationLocked();
10128
10129        if (DEBUG_WINDOW_TRACE) {
10130            Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: animating="
10131                    + mAnimator.mAnimating);
10132        }
10133    }
10134
10135    private int toBrightnessOverride(float value) {
10136        return (int)(value * PowerManager.BRIGHTNESS_ON);
10137    }
10138
10139    void checkDrawnWindowsLocked() {
10140        if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) {
10141            return;
10142        }
10143        for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) {
10144            WindowState win = mWaitingForDrawn.get(j);
10145            if (DEBUG_SCREEN_ON) Slog.i(TAG, "Waiting for drawn " + win +
10146                    ": removed=" + win.mRemoved + " visible=" + win.isVisibleLw() +
10147                    " mHasSurface=" + win.mHasSurface +
10148                    " drawState=" + win.mWinAnimator.mDrawState);
10149            if (win.mRemoved || !win.mHasSurface) {
10150                // Window has been removed; no draw will now happen, so stop waiting.
10151                if (DEBUG_SCREEN_ON) Slog.w(TAG, "Aborted waiting for drawn: " + win);
10152                mWaitingForDrawn.remove(win);
10153            } else if (win.hasDrawnLw()) {
10154                // Window is now drawn (and shown).
10155                if (DEBUG_SCREEN_ON) Slog.d(TAG, "Window drawn win=" + win);
10156                mWaitingForDrawn.remove(win);
10157            }
10158        }
10159        if (mWaitingForDrawn.isEmpty()) {
10160            if (DEBUG_SCREEN_ON) Slog.d(TAG, "All windows drawn!");
10161            mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
10162            mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN);
10163        }
10164    }
10165
10166    void setHoldScreenLocked(final Session newHoldScreen) {
10167        final boolean hold = newHoldScreen != null;
10168
10169        if (hold && mHoldingScreenOn != newHoldScreen) {
10170            mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid));
10171        }
10172        mHoldingScreenOn = newHoldScreen;
10173
10174        final boolean state = mHoldingScreenWakeLock.isHeld();
10175        if (hold != state) {
10176            if (hold) {
10177                mHoldingScreenWakeLock.acquire();
10178                mPolicy.keepScreenOnStartedLw();
10179            } else {
10180                mPolicy.keepScreenOnStoppedLw();
10181                mHoldingScreenWakeLock.release();
10182            }
10183        }
10184    }
10185
10186    void requestTraversal() {
10187        synchronized (mWindowMap) {
10188            requestTraversalLocked();
10189        }
10190    }
10191
10192    void requestTraversalLocked() {
10193        if (!mTraversalScheduled) {
10194            mTraversalScheduled = true;
10195            mH.sendEmptyMessage(H.DO_TRAVERSAL);
10196        }
10197    }
10198
10199    /** Note that Locked in this case is on mLayoutToAnim */
10200    void scheduleAnimationLocked() {
10201        if (!mAnimationScheduled) {
10202            mAnimationScheduled = true;
10203            mChoreographer.postCallback(
10204                    Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null);
10205        }
10206    }
10207
10208    private boolean needsLayout() {
10209        final int numDisplays = mDisplayContents.size();
10210        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10211            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
10212            if (displayContent.layoutNeeded) {
10213                return true;
10214            }
10215        }
10216        return false;
10217    }
10218
10219    boolean copyAnimToLayoutParamsLocked() {
10220        boolean doRequest = false;
10221
10222        final int bulkUpdateParams = mAnimator.mBulkUpdateParams;
10223        if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) {
10224            mInnerFields.mUpdateRotation = true;
10225            doRequest = true;
10226        }
10227        if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) {
10228            mInnerFields.mWallpaperMayChange = true;
10229            doRequest = true;
10230        }
10231        if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) {
10232            mInnerFields.mWallpaperForceHidingChanged = true;
10233            doRequest = true;
10234        }
10235        if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) == 0) {
10236            mInnerFields.mOrientationChangeComplete = false;
10237        } else {
10238            mInnerFields.mOrientationChangeComplete = true;
10239            mInnerFields.mLastWindowFreezeSource = mAnimator.mLastWindowFreezeSource;
10240            if (mWindowsFreezingScreen) {
10241                doRequest = true;
10242            }
10243        }
10244        if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) {
10245            mTurnOnScreen = true;
10246        }
10247        if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_ACTION_PENDING) != 0) {
10248            mInnerFields.mWallpaperActionPending = true;
10249        }
10250
10251        return doRequest;
10252    }
10253
10254    /** If a window that has an animation specifying a colored background and the current wallpaper
10255     * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to
10256     * suddenly disappear. */
10257    int adjustAnimationBackground(WindowStateAnimator winAnimator) {
10258        WindowList windows = winAnimator.mWin.getWindowList();
10259        for (int i = windows.size() - 1; i >= 0; --i) {
10260            WindowState testWin = windows.get(i);
10261            if (testWin.mIsWallpaper && testWin.isVisibleNow()) {
10262                return testWin.mWinAnimator.mAnimLayer;
10263            }
10264        }
10265        return winAnimator.mAnimLayer;
10266    }
10267
10268    boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation,
10269                                           boolean secure) {
10270        final SurfaceControl surface = winAnimator.mSurfaceControl;
10271        boolean leakedSurface = false;
10272        boolean killedApps = false;
10273
10274        EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(),
10275                winAnimator.mSession.mPid, operation);
10276
10277        if (mForceRemoves == null) {
10278            mForceRemoves = new ArrayList<WindowState>();
10279        }
10280
10281        long callingIdentity = Binder.clearCallingIdentity();
10282        try {
10283            // There was some problem...   first, do a sanity check of the
10284            // window list to make sure we haven't left any dangling surfaces
10285            // around.
10286
10287            Slog.i(TAG, "Out of memory for surface!  Looking for leaks...");
10288            final int numDisplays = mDisplayContents.size();
10289            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10290                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
10291                final int numWindows = windows.size();
10292                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
10293                    final WindowState ws = windows.get(winNdx);
10294                    WindowStateAnimator wsa = ws.mWinAnimator;
10295                    if (wsa.mSurfaceControl != null) {
10296                        if (!mSessions.contains(wsa.mSession)) {
10297                            Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): "
10298                                    + ws + " surface=" + wsa.mSurfaceControl
10299                                    + " token=" + ws.mToken
10300                                    + " pid=" + ws.mSession.mPid
10301                                    + " uid=" + ws.mSession.mUid);
10302                            if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null);
10303                            wsa.mSurfaceControl.destroy();
10304                            wsa.mSurfaceShown = false;
10305                            wsa.mSurfaceControl = null;
10306                            ws.mHasSurface = false;
10307                            mForceRemoves.add(ws);
10308                            leakedSurface = true;
10309                        } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) {
10310                            Slog.w(TAG, "LEAKED SURFACE (app token hidden): "
10311                                    + ws + " surface=" + wsa.mSurfaceControl
10312                                    + " token=" + ws.mAppToken);
10313                            if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null);
10314                            wsa.mSurfaceControl.destroy();
10315                            wsa.mSurfaceShown = false;
10316                            wsa.mSurfaceControl = null;
10317                            ws.mHasSurface = false;
10318                            leakedSurface = true;
10319                        }
10320                    }
10321                }
10322            }
10323
10324            if (!leakedSurface) {
10325                Slog.w(TAG, "No leaked surfaces; killing applicatons!");
10326                SparseIntArray pidCandidates = new SparseIntArray();
10327                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10328                    final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
10329                    final int numWindows = windows.size();
10330                    for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
10331                        final WindowState ws = windows.get(winNdx);
10332                        if (mForceRemoves.contains(ws)) {
10333                            continue;
10334                        }
10335                        WindowStateAnimator wsa = ws.mWinAnimator;
10336                        if (wsa.mSurfaceControl != null) {
10337                            pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid);
10338                        }
10339                    }
10340                    if (pidCandidates.size() > 0) {
10341                        int[] pids = new int[pidCandidates.size()];
10342                        for (int i=0; i<pids.length; i++) {
10343                            pids[i] = pidCandidates.keyAt(i);
10344                        }
10345                        try {
10346                            if (mActivityManager.killPids(pids, "Free memory", secure)) {
10347                                killedApps = true;
10348                            }
10349                        } catch (RemoteException e) {
10350                        }
10351                    }
10352                }
10353            }
10354
10355            if (leakedSurface || killedApps) {
10356                // We managed to reclaim some memory, so get rid of the trouble
10357                // surface and ask the app to request another one.
10358                Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry.");
10359                if (surface != null) {
10360                    if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin,
10361                            "RECOVER DESTROY", null);
10362                    surface.destroy();
10363                    winAnimator.mSurfaceShown = false;
10364                    winAnimator.mSurfaceControl = null;
10365                    winAnimator.mWin.mHasSurface = false;
10366                    scheduleRemoveStartingWindowLocked(winAnimator.mWin.mAppToken);
10367                }
10368
10369                try {
10370                    winAnimator.mWin.mClient.dispatchGetNewSurface();
10371                } catch (RemoteException e) {
10372                }
10373            }
10374        } finally {
10375            Binder.restoreCallingIdentity(callingIdentity);
10376        }
10377
10378        return leakedSurface || killedApps;
10379    }
10380
10381    private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
10382        WindowState newFocus = computeFocusedWindowLocked();
10383        if (mCurrentFocus != newFocus) {
10384            Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus");
10385            // This check makes sure that we don't already have the focus
10386            // change message pending.
10387            mH.removeMessages(H.REPORT_FOCUS_CHANGE);
10388            mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
10389            // TODO(multidisplay): Focused windows on default display only.
10390            final DisplayContent displayContent = getDefaultDisplayContentLocked();
10391            final boolean imWindowChanged = moveInputMethodWindowsIfNeededLocked(
10392                    mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS
10393                            && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES);
10394            if (imWindowChanged) {
10395                displayContent.layoutNeeded = true;
10396                newFocus = computeFocusedWindowLocked();
10397            }
10398
10399            if (DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG, "Changing focus from " +
10400                    mCurrentFocus + " to " + newFocus + " Callers=" + Debug.getCallers(4));
10401            final WindowState oldFocus = mCurrentFocus;
10402            mCurrentFocus = newFocus;
10403            mLosingFocus.remove(newFocus);
10404
10405            // TODO(multidisplay): Accessibilty supported only of default desiplay.
10406            if (mAccessibilityController != null
10407                    && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) {
10408                mAccessibilityController.onWindowFocusChangedLocked();
10409            }
10410
10411            int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
10412
10413            if (imWindowChanged && oldFocus != mInputMethodWindow) {
10414                // Focus of the input method window changed. Perform layout if needed.
10415                if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
10416                    performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows);
10417                    focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
10418                } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
10419                    // Client will do the layout, but we need to assign layers
10420                    // for handleNewWindowLocked() below.
10421                    assignLayersLocked(displayContent.getWindowList());
10422                }
10423            }
10424
10425            if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
10426                // The change in focus caused us to need to do a layout.  Okay.
10427                displayContent.layoutNeeded = true;
10428                if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
10429                    performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows);
10430                }
10431            }
10432
10433            if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
10434                // If we defer assigning layers, then the caller is responsible for
10435                // doing this part.
10436                mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows);
10437            }
10438
10439            Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
10440            return true;
10441        }
10442        return false;
10443    }
10444
10445    private WindowState computeFocusedWindowLocked() {
10446        if (mAnimator.mUniverseBackground != null
10447                && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) {
10448            return mAnimator.mUniverseBackground.mWin;
10449        }
10450
10451        final int displayCount = mDisplayContents.size();
10452        for (int i = 0; i < displayCount; i++) {
10453            final DisplayContent displayContent = mDisplayContents.valueAt(i);
10454            WindowState win = findFocusedWindowLocked(displayContent);
10455            if (win != null) {
10456                return win;
10457            }
10458        }
10459        return null;
10460    }
10461
10462    private WindowState findFocusedWindowLocked(DisplayContent displayContent) {
10463        final WindowList windows = displayContent.getWindowList();
10464        for (int i = windows.size() - 1; i >= 0; i--) {
10465            final WindowState win = windows.get(i);
10466
10467            if (localLOGV || DEBUG_FOCUS) Slog.v(
10468                TAG, "Looking for focus: " + i
10469                + " = " + win
10470                + ", flags=" + win.mAttrs.flags
10471                + ", canReceive=" + win.canReceiveKeys());
10472
10473            AppWindowToken wtoken = win.mAppToken;
10474
10475            // If this window's application has been removed, just skip it.
10476            if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) {
10477                if (DEBUG_FOCUS) Slog.v(TAG, "Skipping " + wtoken + " because "
10478                        + (wtoken.removed ? "removed" : "sendingToBottom"));
10479                continue;
10480            }
10481
10482            if (!win.canReceiveKeys()) {
10483                continue;
10484            }
10485
10486            // Descend through all of the app tokens and find the first that either matches
10487            // win.mAppToken (return win) or mFocusedApp (return null).
10488            if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING &&
10489                    mFocusedApp != null) {
10490                ArrayList<Task> tasks = displayContent.getTasks();
10491                for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
10492                    AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
10493                    int tokenNdx = tokens.size() - 1;
10494                    for ( ; tokenNdx >= 0; --tokenNdx) {
10495                        final AppWindowToken token = tokens.get(tokenNdx);
10496                        if (wtoken == token) {
10497                            break;
10498                        }
10499                        if (mFocusedApp == token) {
10500                            // Whoops, we are below the focused app...  no focus for you!
10501                            if (localLOGV || DEBUG_FOCUS_LIGHT) Slog.v(TAG,
10502                                    "findFocusedWindow: Reached focused app=" + mFocusedApp);
10503                            return null;
10504                        }
10505                    }
10506                    if (tokenNdx >= 0) {
10507                        // Early exit from loop, must have found the matching token.
10508                        break;
10509                    }
10510                }
10511            }
10512
10513            if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: Found new focus @ " + i +
10514                        " = " + win);
10515            return win;
10516        }
10517
10518        if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: No focusable windows.");
10519        return null;
10520    }
10521
10522    private void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) {
10523        if (mDisplayFrozen) {
10524            return;
10525        }
10526
10527        if (!mDisplayReady || !mPolicy.isScreenOn()) {
10528            // No need to freeze the screen before the system is ready or if
10529            // the screen is off.
10530            return;
10531        }
10532
10533        mScreenFrozenLock.acquire();
10534
10535        mDisplayFrozen = true;
10536        mDisplayFreezeTime = SystemClock.elapsedRealtime();
10537        mLastFinishedFreezeSource = null;
10538
10539        mInputMonitor.freezeInputDispatchingLw();
10540
10541        // Clear the last input window -- that is just used for
10542        // clean transitions between IMEs, and if we are freezing
10543        // the screen then the whole world is changing behind the scenes.
10544        mPolicy.setLastInputMethodWindowLw(null, null);
10545
10546        if (mAppTransition.isTransitionSet()) {
10547            mAppTransition.freeze();
10548        }
10549
10550        if (PROFILE_ORIENTATION) {
10551            File file = new File("/data/system/frozen");
10552            Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
10553        }
10554
10555        if (CUSTOM_SCREEN_ROTATION) {
10556            mExitAnimId = exitAnim;
10557            mEnterAnimId = enterAnim;
10558            final DisplayContent displayContent = getDefaultDisplayContentLocked();
10559            final int displayId = displayContent.getDisplayId();
10560            ScreenRotationAnimation screenRotationAnimation =
10561                    mAnimator.getScreenRotationAnimationLocked(displayId);
10562            if (screenRotationAnimation != null) {
10563                screenRotationAnimation.kill();
10564            }
10565
10566            // Check whether the current screen contains any secure content.
10567            boolean isSecure = false;
10568            final WindowList windows = getDefaultWindowListLocked();
10569            final int N = windows.size();
10570            for (int i = 0; i < N; i++) {
10571                WindowState ws = windows.get(i);
10572                if (ws.isOnScreen() && (ws.mAttrs.flags & FLAG_SECURE) != 0) {
10573                    isSecure = true;
10574                    break;
10575                }
10576            }
10577
10578            // TODO(multidisplay): rotation on main screen only.
10579            displayContent.updateDisplayInfo();
10580            screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent,
10581                    mFxSession, inTransaction, mPolicy.isDefaultOrientationForced(), isSecure);
10582            mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
10583        }
10584    }
10585
10586    private void stopFreezingDisplayLocked() {
10587        if (!mDisplayFrozen) {
10588            return;
10589        }
10590
10591        if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen
10592                || mClientFreezingScreen) {
10593            if (DEBUG_ORIENTATION) Slog.d(TAG,
10594                "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig
10595                + ", mAppsFreezingScreen=" + mAppsFreezingScreen
10596                + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen
10597                + ", mClientFreezingScreen=" + mClientFreezingScreen);
10598            return;
10599        }
10600
10601        mDisplayFrozen = false;
10602        mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime);
10603        StringBuilder sb = new StringBuilder(128);
10604        sb.append("Screen frozen for ");
10605        TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb);
10606        if (mLastFinishedFreezeSource != null) {
10607            sb.append(" due to ");
10608            sb.append(mLastFinishedFreezeSource);
10609        }
10610        Slog.i(TAG, sb.toString());
10611        mH.removeMessages(H.APP_FREEZE_TIMEOUT);
10612        mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
10613        if (PROFILE_ORIENTATION) {
10614            Debug.stopMethodTracing();
10615        }
10616
10617        boolean updateRotation = false;
10618
10619        final DisplayContent displayContent = getDefaultDisplayContentLocked();
10620        final int displayId = displayContent.getDisplayId();
10621        ScreenRotationAnimation screenRotationAnimation =
10622                mAnimator.getScreenRotationAnimationLocked(displayId);
10623        if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
10624                && screenRotationAnimation.hasScreenshot()) {
10625            if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation");
10626            // TODO(multidisplay): rotation on main screen only.
10627            DisplayInfo displayInfo = displayContent.getDisplayInfo();
10628            // Get rotation animation again, with new top window
10629            boolean isDimming = displayContent.isDimming();
10630            if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) {
10631                mExitAnimId = mEnterAnimId = 0;
10632            }
10633            if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
10634                    getTransitionAnimationScaleLocked(), displayInfo.logicalWidth,
10635                        displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) {
10636                scheduleAnimationLocked();
10637            } else {
10638                screenRotationAnimation.kill();
10639                screenRotationAnimation = null;
10640                mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
10641                updateRotation = true;
10642            }
10643        } else {
10644            if (screenRotationAnimation != null) {
10645                screenRotationAnimation.kill();
10646                screenRotationAnimation = null;
10647                mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
10648            }
10649            updateRotation = true;
10650        }
10651
10652        mInputMonitor.thawInputDispatchingLw();
10653
10654        boolean configChanged;
10655
10656        // While the display is frozen we don't re-compute the orientation
10657        // to avoid inconsistent states.  However, something interesting
10658        // could have actually changed during that time so re-evaluate it
10659        // now to catch that.
10660        configChanged = updateOrientationFromAppTokensLocked(false);
10661
10662        // A little kludge: a lot could have happened while the
10663        // display was frozen, so now that we are coming back we
10664        // do a gc so that any remote references the system
10665        // processes holds on others can be released if they are
10666        // no longer needed.
10667        mH.removeMessages(H.FORCE_GC);
10668        mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000);
10669
10670        mScreenFrozenLock.release();
10671
10672        if (updateRotation) {
10673            if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
10674            configChanged |= updateRotationUncheckedLocked(false);
10675        }
10676
10677        if (configChanged) {
10678            mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
10679        }
10680    }
10681
10682    static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps,
10683            DisplayMetrics dm) {
10684        if (index < tokens.length) {
10685            String str = tokens[index];
10686            if (str != null && str.length() > 0) {
10687                try {
10688                    int val = Integer.parseInt(str);
10689                    return val;
10690                } catch (Exception e) {
10691                }
10692            }
10693        }
10694        if (defUnits == TypedValue.COMPLEX_UNIT_PX) {
10695            return defDps;
10696        }
10697        int val = (int)TypedValue.applyDimension(defUnits, defDps, dm);
10698        return val;
10699    }
10700
10701    void createWatermarkInTransaction() {
10702        if (mWatermark != null) {
10703            return;
10704        }
10705
10706        File file = new File("/system/etc/setup.conf");
10707        FileInputStream in = null;
10708        DataInputStream ind = null;
10709        try {
10710            in = new FileInputStream(file);
10711            ind = new DataInputStream(in);
10712            String line = ind.readLine();
10713            if (line != null) {
10714                String[] toks = line.split("%");
10715                if (toks != null && toks.length > 0) {
10716                    mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(),
10717                            mRealDisplayMetrics, mFxSession, toks);
10718                }
10719            }
10720        } catch (FileNotFoundException e) {
10721        } catch (IOException e) {
10722        } finally {
10723            if (ind != null) {
10724                try {
10725                    ind.close();
10726                } catch (IOException e) {
10727                }
10728            } else if (in != null) {
10729                try {
10730                    in.close();
10731                } catch (IOException e) {
10732                }
10733            }
10734        }
10735    }
10736
10737    @Override
10738    public void statusBarVisibilityChanged(int visibility) {
10739        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
10740                != PackageManager.PERMISSION_GRANTED) {
10741            throw new SecurityException("Caller does not hold permission "
10742                    + android.Manifest.permission.STATUS_BAR);
10743        }
10744
10745        synchronized (mWindowMap) {
10746            mLastStatusBarVisibility = visibility;
10747            visibility = mPolicy.adjustSystemUiVisibilityLw(visibility);
10748            updateStatusBarVisibilityLocked(visibility);
10749        }
10750    }
10751
10752    // TOOD(multidisplay): StatusBar on multiple screens?
10753    void updateStatusBarVisibilityLocked(int visibility) {
10754        mInputManager.setSystemUiVisibility(visibility);
10755        final WindowList windows = getDefaultWindowListLocked();
10756        final int N = windows.size();
10757        for (int i = 0; i < N; i++) {
10758            WindowState ws = windows.get(i);
10759            try {
10760                int curValue = ws.mSystemUiVisibility;
10761                int diff = curValue ^ visibility;
10762                // We are only interested in differences of one of the
10763                // clearable flags...
10764                diff &= View.SYSTEM_UI_CLEARABLE_FLAGS;
10765                // ...if it has actually been cleared.
10766                diff &= ~visibility;
10767                int newValue = (curValue&~diff) | (visibility&diff);
10768                if (newValue != curValue) {
10769                    ws.mSeq++;
10770                    ws.mSystemUiVisibility = newValue;
10771                }
10772                if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) {
10773                    ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq,
10774                            visibility, newValue, diff);
10775                }
10776            } catch (RemoteException e) {
10777                // so sorry
10778            }
10779        }
10780    }
10781
10782    @Override
10783    public void reevaluateStatusBarVisibility() {
10784        synchronized (mWindowMap) {
10785            int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility);
10786            updateStatusBarVisibilityLocked(visibility);
10787            performLayoutAndPlaceSurfacesLocked();
10788        }
10789    }
10790
10791    @Override
10792    public FakeWindow addFakeWindow(Looper looper,
10793            InputEventReceiver.Factory inputEventReceiverFactory,
10794            String name, int windowType, int layoutParamsFlags, int layoutParamsPrivateFlags,
10795            boolean canReceiveKeys, boolean hasFocus, boolean touchFullscreen) {
10796        synchronized (mWindowMap) {
10797            FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputEventReceiverFactory,
10798                    name, windowType, layoutParamsFlags, canReceiveKeys, hasFocus, touchFullscreen);
10799            int i=0;
10800            while (i<mFakeWindows.size()) {
10801                if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) {
10802                    break;
10803                }
10804            }
10805            mFakeWindows.add(i, fw);
10806            mInputMonitor.updateInputWindowsLw(true);
10807            return fw;
10808        }
10809    }
10810
10811    boolean removeFakeWindowLocked(FakeWindow window) {
10812        synchronized (mWindowMap) {
10813            if (mFakeWindows.remove(window)) {
10814                mInputMonitor.updateInputWindowsLw(true);
10815                return true;
10816            }
10817            return false;
10818        }
10819    }
10820
10821    // It is assumed that this method is called only by InputMethodManagerService.
10822    public void saveLastInputMethodWindowForTransition() {
10823        synchronized (mWindowMap) {
10824            // TODO(multidisplay): Pass in the displayID.
10825            DisplayContent displayContent = getDefaultDisplayContentLocked();
10826            if (mInputMethodWindow != null) {
10827                mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget);
10828            }
10829        }
10830    }
10831
10832    public int getInputMethodWindowVisibleHeight() {
10833        synchronized (mWindowMap) {
10834            return mPolicy.getInputMethodWindowVisibleHeightLw();
10835        }
10836    }
10837
10838    @Override
10839    public boolean hasNavigationBar() {
10840        return mPolicy.hasNavigationBar();
10841    }
10842
10843    @Override
10844    public void lockNow(Bundle options) {
10845        mPolicy.lockNow(options);
10846    }
10847
10848    public void showRecentApps() {
10849        mPolicy.showRecentApps();
10850    }
10851
10852    @Override
10853    public boolean isSafeModeEnabled() {
10854        return mSafeMode;
10855    }
10856
10857    @Override
10858    public boolean clearWindowContentFrameStats(IBinder token) {
10859        if (!checkCallingPermission(Manifest.permission.FRAME_STATS,
10860                "clearWindowContentFrameStats()")) {
10861            throw new SecurityException("Requires FRAME_STATS permission");
10862        }
10863        synchronized (mWindowMap) {
10864            WindowState windowState = mWindowMap.get(token);
10865            if (windowState == null) {
10866                return false;
10867            }
10868            SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl;
10869            if (surfaceControl == null) {
10870                return false;
10871            }
10872            return surfaceControl.clearContentFrameStats();
10873        }
10874    }
10875
10876    @Override
10877    public WindowContentFrameStats getWindowContentFrameStats(IBinder token) {
10878        if (!checkCallingPermission(Manifest.permission.FRAME_STATS,
10879                "getWindowContentFrameStats()")) {
10880            throw new SecurityException("Requires FRAME_STATS permission");
10881        }
10882        synchronized (mWindowMap) {
10883            WindowState windowState = mWindowMap.get(token);
10884            if (windowState == null) {
10885                return null;
10886            }
10887            SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl;
10888            if (surfaceControl == null) {
10889                return null;
10890            }
10891            if (mTempWindowRenderStats == null) {
10892                mTempWindowRenderStats = new WindowContentFrameStats();
10893            }
10894            WindowContentFrameStats stats = mTempWindowRenderStats;
10895            if (!surfaceControl.getContentFrameStats(stats)) {
10896                return null;
10897            }
10898            return stats;
10899        }
10900    }
10901
10902    void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) {
10903        pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)");
10904        mPolicy.dump("    ", pw, args);
10905    }
10906
10907    void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) {
10908        pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)");
10909        mAnimator.dumpLocked(pw, "    ", dumpAll);
10910    }
10911
10912    void dumpTokensLocked(PrintWriter pw, boolean dumpAll) {
10913        pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)");
10914        if (mTokenMap.size() > 0) {
10915            pw.println("  All tokens:");
10916            Iterator<WindowToken> it = mTokenMap.values().iterator();
10917            while (it.hasNext()) {
10918                WindowToken token = it.next();
10919                pw.print("  "); pw.print(token);
10920                if (dumpAll) {
10921                    pw.println(':');
10922                    token.dump(pw, "    ");
10923                } else {
10924                    pw.println();
10925                }
10926            }
10927        }
10928        if (mWallpaperTokens.size() > 0) {
10929            pw.println();
10930            pw.println("  Wallpaper tokens:");
10931            for (int i=mWallpaperTokens.size()-1; i>=0; i--) {
10932                WindowToken token = mWallpaperTokens.get(i);
10933                pw.print("  Wallpaper #"); pw.print(i);
10934                        pw.print(' '); pw.print(token);
10935                if (dumpAll) {
10936                    pw.println(':');
10937                    token.dump(pw, "    ");
10938                } else {
10939                    pw.println();
10940                }
10941            }
10942        }
10943        if (mFinishedStarting.size() > 0) {
10944            pw.println();
10945            pw.println("  Finishing start of application tokens:");
10946            for (int i=mFinishedStarting.size()-1; i>=0; i--) {
10947                WindowToken token = mFinishedStarting.get(i);
10948                pw.print("  Finished Starting #"); pw.print(i);
10949                        pw.print(' '); pw.print(token);
10950                if (dumpAll) {
10951                    pw.println(':');
10952                    token.dump(pw, "    ");
10953                } else {
10954                    pw.println();
10955                }
10956            }
10957        }
10958        if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) {
10959            pw.println();
10960            if (mOpeningApps.size() > 0) {
10961                pw.print("  mOpeningApps="); pw.println(mOpeningApps);
10962            }
10963            if (mClosingApps.size() > 0) {
10964                pw.print("  mClosingApps="); pw.println(mClosingApps);
10965            }
10966        }
10967    }
10968
10969    void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) {
10970        pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)");
10971        for (int i=0; i<mSessions.size(); i++) {
10972            Session s = mSessions.valueAt(i);
10973            pw.print("  Session "); pw.print(s); pw.println(':');
10974            s.dump(pw, "    ");
10975        }
10976    }
10977
10978    void dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll) {
10979        pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)");
10980        if (mDisplayReady) {
10981            final int numDisplays = mDisplayContents.size();
10982            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10983                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
10984                displayContent.dump("  ", pw);
10985            }
10986        } else {
10987            pw.println("  NO DISPLAY");
10988        }
10989    }
10990
10991    void dumpWindowsLocked(PrintWriter pw, boolean dumpAll,
10992            ArrayList<WindowState> windows) {
10993        pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)");
10994        dumpWindowsNoHeaderLocked(pw, dumpAll, windows);
10995    }
10996
10997    void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll,
10998            ArrayList<WindowState> windows) {
10999        final int numDisplays = mDisplayContents.size();
11000        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
11001            final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList();
11002            for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
11003                final WindowState w = windowList.get(winNdx);
11004                if (windows == null || windows.contains(w)) {
11005                    pw.print("  Window #"); pw.print(winNdx); pw.print(' ');
11006                            pw.print(w); pw.println(":");
11007                    w.dump(pw, "    ", dumpAll || windows != null);
11008                }
11009            }
11010        }
11011        if (mInputMethodDialogs.size() > 0) {
11012            pw.println();
11013            pw.println("  Input method dialogs:");
11014            for (int i=mInputMethodDialogs.size()-1; i>=0; i--) {
11015                WindowState w = mInputMethodDialogs.get(i);
11016                if (windows == null || windows.contains(w)) {
11017                    pw.print("  IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w);
11018                }
11019            }
11020        }
11021        if (mPendingRemove.size() > 0) {
11022            pw.println();
11023            pw.println("  Remove pending for:");
11024            for (int i=mPendingRemove.size()-1; i>=0; i--) {
11025                WindowState w = mPendingRemove.get(i);
11026                if (windows == null || windows.contains(w)) {
11027                    pw.print("  Remove #"); pw.print(i); pw.print(' ');
11028                            pw.print(w);
11029                    if (dumpAll) {
11030                        pw.println(":");
11031                        w.dump(pw, "    ", true);
11032                    } else {
11033                        pw.println();
11034                    }
11035                }
11036            }
11037        }
11038        if (mForceRemoves != null && mForceRemoves.size() > 0) {
11039            pw.println();
11040            pw.println("  Windows force removing:");
11041            for (int i=mForceRemoves.size()-1; i>=0; i--) {
11042                WindowState w = mForceRemoves.get(i);
11043                pw.print("  Removing #"); pw.print(i); pw.print(' ');
11044                        pw.print(w);
11045                if (dumpAll) {
11046                    pw.println(":");
11047                    w.dump(pw, "    ", true);
11048                } else {
11049                    pw.println();
11050                }
11051            }
11052        }
11053        if (mDestroySurface.size() > 0) {
11054            pw.println();
11055            pw.println("  Windows waiting to destroy their surface:");
11056            for (int i=mDestroySurface.size()-1; i>=0; i--) {
11057                WindowState w = mDestroySurface.get(i);
11058                if (windows == null || windows.contains(w)) {
11059                    pw.print("  Destroy #"); pw.print(i); pw.print(' ');
11060                            pw.print(w);
11061                    if (dumpAll) {
11062                        pw.println(":");
11063                        w.dump(pw, "    ", true);
11064                    } else {
11065                        pw.println();
11066                    }
11067                }
11068            }
11069        }
11070        if (mLosingFocus.size() > 0) {
11071            pw.println();
11072            pw.println("  Windows losing focus:");
11073            for (int i=mLosingFocus.size()-1; i>=0; i--) {
11074                WindowState w = mLosingFocus.get(i);
11075                if (windows == null || windows.contains(w)) {
11076                    pw.print("  Losing #"); pw.print(i); pw.print(' ');
11077                            pw.print(w);
11078                    if (dumpAll) {
11079                        pw.println(":");
11080                        w.dump(pw, "    ", true);
11081                    } else {
11082                        pw.println();
11083                    }
11084                }
11085            }
11086        }
11087        if (mResizingWindows.size() > 0) {
11088            pw.println();
11089            pw.println("  Windows waiting to resize:");
11090            for (int i=mResizingWindows.size()-1; i>=0; i--) {
11091                WindowState w = mResizingWindows.get(i);
11092                if (windows == null || windows.contains(w)) {
11093                    pw.print("  Resizing #"); pw.print(i); pw.print(' ');
11094                            pw.print(w);
11095                    if (dumpAll) {
11096                        pw.println(":");
11097                        w.dump(pw, "    ", true);
11098                    } else {
11099                        pw.println();
11100                    }
11101                }
11102            }
11103        }
11104        if (mWaitingForDrawn.size() > 0) {
11105            pw.println();
11106            pw.println("  Clients waiting for these windows to be drawn:");
11107            for (int i=mWaitingForDrawn.size()-1; i>=0; i--) {
11108                WindowState win = mWaitingForDrawn.get(i);
11109                pw.print("  Waiting #"); pw.print(i); pw.print(' '); pw.print(win);
11110            }
11111        }
11112        pw.println();
11113        pw.print("  mCurConfiguration="); pw.println(this.mCurConfiguration);
11114        pw.print("  mHasPermanentDpad="); pw.println(mHasPermanentDpad);
11115        pw.print("  mCurrentFocus="); pw.println(mCurrentFocus);
11116        if (mLastFocus != mCurrentFocus) {
11117            pw.print("  mLastFocus="); pw.println(mLastFocus);
11118        }
11119        pw.print("  mFocusedApp="); pw.println(mFocusedApp);
11120        if (mInputMethodTarget != null) {
11121            pw.print("  mInputMethodTarget="); pw.println(mInputMethodTarget);
11122        }
11123        pw.print("  mInTouchMode="); pw.print(mInTouchMode);
11124                pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
11125        pw.print("  mLastDisplayFreezeDuration=");
11126                TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw);
11127                if ( mLastFinishedFreezeSource != null) {
11128                    pw.print(" due to ");
11129                    pw.print(mLastFinishedFreezeSource);
11130                }
11131                pw.println();
11132        if (dumpAll) {
11133            pw.print("  mSystemDecorLayer="); pw.print(mSystemDecorLayer);
11134                    pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString());
11135            if (mLastStatusBarVisibility != 0) {
11136                pw.print("  mLastStatusBarVisibility=0x");
11137                        pw.println(Integer.toHexString(mLastStatusBarVisibility));
11138            }
11139            if (mInputMethodWindow != null) {
11140                pw.print("  mInputMethodWindow="); pw.println(mInputMethodWindow);
11141            }
11142            pw.print("  mWallpaperTarget="); pw.println(mWallpaperTarget);
11143            if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) {
11144                pw.print("  mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget);
11145                pw.print("  mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget);
11146            }
11147            pw.print("  mLastWallpaperX="); pw.print(mLastWallpaperX);
11148                    pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
11149            if (mLastWallpaperDisplayOffsetX != Integer.MIN_VALUE
11150                    || mLastWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
11151                pw.print("  mLastWallpaperDisplayOffsetX="); pw.print(mLastWallpaperDisplayOffsetX);
11152                        pw.print(" mLastWallpaperDisplayOffsetY=");
11153                        pw.println(mLastWallpaperDisplayOffsetY);
11154            }
11155            if (mInputMethodAnimLayerAdjustment != 0 ||
11156                    mWallpaperAnimLayerAdjustment != 0) {
11157                pw.print("  mInputMethodAnimLayerAdjustment=");
11158                        pw.print(mInputMethodAnimLayerAdjustment);
11159                        pw.print("  mWallpaperAnimLayerAdjustment=");
11160                        pw.println(mWallpaperAnimLayerAdjustment);
11161            }
11162            pw.print("  mSystemBooted="); pw.print(mSystemBooted);
11163                    pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
11164            if (needsLayout()) {
11165                pw.print("  layoutNeeded on displays=");
11166                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
11167                    final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
11168                    if (displayContent.layoutNeeded) {
11169                        pw.print(displayContent.getDisplayId());
11170                    }
11171                }
11172                pw.println();
11173            }
11174            pw.print("  mTransactionSequence="); pw.println(mTransactionSequence);
11175            pw.print("  mDisplayFrozen="); pw.print(mDisplayFrozen);
11176                    pw.print(" windows="); pw.print(mWindowsFreezingScreen);
11177                    pw.print(" client="); pw.print(mClientFreezingScreen);
11178                    pw.print(" apps="); pw.print(mAppsFreezingScreen);
11179                    pw.print(" waitingForConfig="); pw.println(mWaitingForConfig);
11180            pw.print("  mRotation="); pw.print(mRotation);
11181                    pw.print(" mAltOrientation="); pw.println(mAltOrientation);
11182            pw.print("  mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation);
11183                    pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation);
11184            pw.print("  mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount);
11185            pw.print("  Animation settings: disabled="); pw.print(mAnimationsDisabled);
11186                    pw.print(" window="); pw.print(mWindowAnimationScaleSetting);
11187                    pw.print(" transition="); pw.print(mTransitionAnimationScaleSetting);
11188                    pw.print(" animator="); pw.println(mAnimatorDurationScaleSetting);
11189            pw.print("  mTraversalScheduled="); pw.println(mTraversalScheduled);
11190            pw.print("  mStartingIconInTransition="); pw.print(mStartingIconInTransition);
11191                    pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
11192            pw.println("  mLayoutToAnim:");
11193            mAppTransition.dump(pw);
11194        }
11195    }
11196
11197    boolean dumpWindows(PrintWriter pw, String name, String[] args,
11198            int opti, boolean dumpAll) {
11199        WindowList windows = new WindowList();
11200        if ("visible".equals(name)) {
11201            synchronized(mWindowMap) {
11202                final int numDisplays = mDisplayContents.size();
11203                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
11204                    final WindowList windowList =
11205                            mDisplayContents.valueAt(displayNdx).getWindowList();
11206                    for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
11207                        final WindowState w = windowList.get(winNdx);
11208                        if (w.mWinAnimator.mSurfaceShown) {
11209                            windows.add(w);
11210                        }
11211                    }
11212                }
11213            }
11214        } else {
11215            int objectId = 0;
11216            // See if this is an object ID.
11217            try {
11218                objectId = Integer.parseInt(name, 16);
11219                name = null;
11220            } catch (RuntimeException e) {
11221            }
11222            synchronized(mWindowMap) {
11223                final int numDisplays = mDisplayContents.size();
11224                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
11225                    final WindowList windowList =
11226                            mDisplayContents.valueAt(displayNdx).getWindowList();
11227                    for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
11228                        final WindowState w = windowList.get(winNdx);
11229                        if (name != null) {
11230                            if (w.mAttrs.getTitle().toString().contains(name)) {
11231                                windows.add(w);
11232                            }
11233                        } else if (System.identityHashCode(w) == objectId) {
11234                            windows.add(w);
11235                        }
11236                    }
11237                }
11238            }
11239        }
11240
11241        if (windows.size() <= 0) {
11242            return false;
11243        }
11244
11245        synchronized(mWindowMap) {
11246            dumpWindowsLocked(pw, dumpAll, windows);
11247        }
11248        return true;
11249    }
11250
11251    void dumpLastANRLocked(PrintWriter pw) {
11252        pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)");
11253        if (mLastANRState == null) {
11254            pw.println("  <no ANR has occurred since boot>");
11255        } else {
11256            pw.println(mLastANRState);
11257        }
11258    }
11259
11260    /**
11261     * Saves information about the state of the window manager at
11262     * the time an ANR occurred before anything else in the system changes
11263     * in response.
11264     *
11265     * @param appWindowToken The application that ANR'd, may be null.
11266     * @param windowState The window that ANR'd, may be null.
11267     * @param reason The reason for the ANR, may be null.
11268     */
11269    public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState,
11270            String reason) {
11271        StringWriter sw = new StringWriter();
11272        PrintWriter pw = new FastPrintWriter(sw, false, 1024);
11273        pw.println("  ANR time: " + DateFormat.getInstance().format(new Date()));
11274        if (appWindowToken != null) {
11275            pw.println("  Application at fault: " + appWindowToken.stringName);
11276        }
11277        if (windowState != null) {
11278            pw.println("  Window at fault: " + windowState.mAttrs.getTitle());
11279        }
11280        if (reason != null) {
11281            pw.println("  Reason: " + reason);
11282        }
11283        pw.println();
11284        dumpWindowsNoHeaderLocked(pw, true, null);
11285        pw.close();
11286        mLastANRState = sw.toString();
11287    }
11288
11289    @Override
11290    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
11291        if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
11292                != PackageManager.PERMISSION_GRANTED) {
11293            pw.println("Permission Denial: can't dump WindowManager from from pid="
11294                    + Binder.getCallingPid()
11295                    + ", uid=" + Binder.getCallingUid());
11296            return;
11297        }
11298
11299        boolean dumpAll = false;
11300
11301        int opti = 0;
11302        while (opti < args.length) {
11303            String opt = args[opti];
11304            if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
11305                break;
11306            }
11307            opti++;
11308            if ("-a".equals(opt)) {
11309                dumpAll = true;
11310            } else if ("-h".equals(opt)) {
11311                pw.println("Window manager dump options:");
11312                pw.println("  [-a] [-h] [cmd] ...");
11313                pw.println("  cmd may be one of:");
11314                pw.println("    l[astanr]: last ANR information");
11315                pw.println("    p[policy]: policy state");
11316                pw.println("    a[animator]: animator state");
11317                pw.println("    s[essions]: active sessions");
11318                pw.println("    surfaces: active surfaces (debugging enabled only)");
11319                pw.println("    d[isplays]: active display contents");
11320                pw.println("    t[okens]: token list");
11321                pw.println("    w[indows]: window list");
11322                pw.println("  cmd may also be a NAME to dump windows.  NAME may");
11323                pw.println("    be a partial substring in a window name, a");
11324                pw.println("    Window hex object identifier, or");
11325                pw.println("    \"all\" for all windows, or");
11326                pw.println("    \"visible\" for the visible windows.");
11327                pw.println("  -a: include all available server state.");
11328                return;
11329            } else {
11330                pw.println("Unknown argument: " + opt + "; use -h for help");
11331            }
11332        }
11333
11334        // Is the caller requesting to dump a particular piece of data?
11335        if (opti < args.length) {
11336            String cmd = args[opti];
11337            opti++;
11338            if ("lastanr".equals(cmd) || "l".equals(cmd)) {
11339                synchronized(mWindowMap) {
11340                    dumpLastANRLocked(pw);
11341                }
11342                return;
11343            } else if ("policy".equals(cmd) || "p".equals(cmd)) {
11344                synchronized(mWindowMap) {
11345                    dumpPolicyLocked(pw, args, true);
11346                }
11347                return;
11348            } else if ("animator".equals(cmd) || "a".equals(cmd)) {
11349                synchronized(mWindowMap) {
11350                    dumpAnimatorLocked(pw, args, true);
11351                }
11352                return;
11353            } else if ("sessions".equals(cmd) || "s".equals(cmd)) {
11354                synchronized(mWindowMap) {
11355                    dumpSessionsLocked(pw, true);
11356                }
11357                return;
11358            } else if ("surfaces".equals(cmd)) {
11359                synchronized(mWindowMap) {
11360                    WindowStateAnimator.SurfaceTrace.dumpAllSurfaces(pw, null);
11361                }
11362                return;
11363            } else if ("displays".equals(cmd) || "d".equals(cmd)) {
11364                synchronized(mWindowMap) {
11365                    dumpDisplayContentsLocked(pw, true);
11366                }
11367                return;
11368            } else if ("tokens".equals(cmd) || "t".equals(cmd)) {
11369                synchronized(mWindowMap) {
11370                    dumpTokensLocked(pw, true);
11371                }
11372                return;
11373            } else if ("windows".equals(cmd) || "w".equals(cmd)) {
11374                synchronized(mWindowMap) {
11375                    dumpWindowsLocked(pw, true, null);
11376                }
11377                return;
11378            } else if ("all".equals(cmd) || "a".equals(cmd)) {
11379                synchronized(mWindowMap) {
11380                    dumpWindowsLocked(pw, true, null);
11381                }
11382                return;
11383            } else {
11384                // Dumping a single name?
11385                if (!dumpWindows(pw, cmd, args, opti, dumpAll)) {
11386                    pw.println("Bad window command, or no windows match: " + cmd);
11387                    pw.println("Use -h for help.");
11388                }
11389                return;
11390            }
11391        }
11392
11393        synchronized(mWindowMap) {
11394            pw.println();
11395            if (dumpAll) {
11396                pw.println("-------------------------------------------------------------------------------");
11397            }
11398            dumpLastANRLocked(pw);
11399            pw.println();
11400            if (dumpAll) {
11401                pw.println("-------------------------------------------------------------------------------");
11402            }
11403            dumpPolicyLocked(pw, args, dumpAll);
11404            pw.println();
11405            if (dumpAll) {
11406                pw.println("-------------------------------------------------------------------------------");
11407            }
11408            dumpAnimatorLocked(pw, args, dumpAll);
11409            pw.println();
11410            if (dumpAll) {
11411                pw.println("-------------------------------------------------------------------------------");
11412            }
11413            dumpSessionsLocked(pw, dumpAll);
11414            pw.println();
11415            if (dumpAll) {
11416                pw.println("-------------------------------------------------------------------------------");
11417            }
11418            WindowStateAnimator.SurfaceTrace.dumpAllSurfaces(pw, dumpAll ?
11419                    "-------------------------------------------------------------------------------"
11420                    : null);
11421            pw.println();
11422            if (dumpAll) {
11423                pw.println("-------------------------------------------------------------------------------");
11424            }
11425            dumpDisplayContentsLocked(pw, dumpAll);
11426            pw.println();
11427            if (dumpAll) {
11428                pw.println("-------------------------------------------------------------------------------");
11429            }
11430            dumpTokensLocked(pw, dumpAll);
11431            pw.println();
11432            if (dumpAll) {
11433                pw.println("-------------------------------------------------------------------------------");
11434            }
11435            dumpWindowsLocked(pw, dumpAll, null);
11436        }
11437    }
11438
11439    // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection).
11440    @Override
11441    public void monitor() {
11442        synchronized (mWindowMap) { }
11443    }
11444
11445    public interface OnHardKeyboardStatusChangeListener {
11446        public void onHardKeyboardStatusChange(boolean available);
11447    }
11448
11449    void debugLayoutRepeats(final String msg, int pendingLayoutChanges) {
11450        if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) {
11451            Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" +
11452                    Integer.toHexString(pendingLayoutChanges));
11453        }
11454    }
11455
11456    private DisplayContent newDisplayContentLocked(final Display display) {
11457        DisplayContent displayContent = new DisplayContent(display, this);
11458        final int displayId = display.getDisplayId();
11459        if (DEBUG_DISPLAY) Slog.v(TAG, "Adding display=" + display);
11460        mDisplayContents.put(displayId, displayContent);
11461
11462        DisplayInfo displayInfo = displayContent.getDisplayInfo();
11463        final Rect rect = new Rect();
11464        mDisplaySettings.getOverscanLocked(displayInfo.name, displayInfo.uniqueId, rect);
11465        synchronized (displayContent.mDisplaySizeLock) {
11466            displayInfo.overscanLeft = rect.left;
11467            displayInfo.overscanTop = rect.top;
11468            displayInfo.overscanRight = rect.right;
11469            displayInfo.overscanBottom = rect.bottom;
11470            mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
11471                    displayId, displayInfo);
11472        }
11473        configureDisplayPolicyLocked(displayContent);
11474
11475        // TODO: Create an input channel for each display with touch capability.
11476        if (displayId == Display.DEFAULT_DISPLAY) {
11477            displayContent.mTapDetector = new StackTapPointerEventListener(this, displayContent);
11478            registerPointerEventListener(displayContent.mTapDetector);
11479        }
11480
11481        return displayContent;
11482    }
11483
11484    public void createDisplayContentLocked(final Display display) {
11485        if (display == null) {
11486            throw new IllegalArgumentException("getDisplayContent: display must not be null");
11487        }
11488        getDisplayContentLocked(display.getDisplayId());
11489    }
11490
11491    /**
11492     * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if
11493     * there is a Display for the displayId.
11494     * @param displayId The display the caller is interested in.
11495     * @return The DisplayContent associated with displayId or null if there is no Display for it.
11496     */
11497    public DisplayContent getDisplayContentLocked(final int displayId) {
11498        DisplayContent displayContent = mDisplayContents.get(displayId);
11499        if (displayContent == null) {
11500            final Display display = mDisplayManager.getDisplay(displayId);
11501            if (display != null) {
11502                displayContent = newDisplayContentLocked(display);
11503            }
11504        }
11505        return displayContent;
11506    }
11507
11508    // There is an inherent assumption that this will never return null.
11509    public DisplayContent getDefaultDisplayContentLocked() {
11510        return getDisplayContentLocked(Display.DEFAULT_DISPLAY);
11511    }
11512
11513    public WindowList getDefaultWindowListLocked() {
11514        return getDefaultDisplayContentLocked().getWindowList();
11515    }
11516
11517    public DisplayInfo getDefaultDisplayInfoLocked() {
11518        return getDefaultDisplayContentLocked().getDisplayInfo();
11519    }
11520
11521    /**
11522     * Return the list of WindowStates associated on the passed display.
11523     * @param display The screen to return windows from.
11524     * @return The list of WindowStates on the screen, or null if the there is no screen.
11525     */
11526    public WindowList getWindowListLocked(final Display display) {
11527        return getWindowListLocked(display.getDisplayId());
11528    }
11529
11530    /**
11531     * Return the list of WindowStates associated on the passed display.
11532     * @param displayId The screen to return windows from.
11533     * @return The list of WindowStates on the screen, or null if the there is no screen.
11534     */
11535    public WindowList getWindowListLocked(final int displayId) {
11536        final DisplayContent displayContent = getDisplayContentLocked(displayId);
11537        return displayContent != null ? displayContent.getWindowList() : null;
11538    }
11539
11540    public void onDisplayAdded(int displayId) {
11541        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0));
11542    }
11543
11544    public void handleDisplayAdded(int displayId) {
11545        synchronized (mWindowMap) {
11546            final Display display = mDisplayManager.getDisplay(displayId);
11547            if (display != null) {
11548                createDisplayContentLocked(display);
11549                displayReady(displayId);
11550            }
11551            requestTraversalLocked();
11552        }
11553    }
11554
11555    public void onDisplayRemoved(int displayId) {
11556        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0));
11557    }
11558
11559    private void handleDisplayRemovedLocked(int displayId) {
11560        final DisplayContent displayContent = getDisplayContentLocked(displayId);
11561        if (displayContent != null) {
11562            if (displayContent.isAnimating()) {
11563                displayContent.mDeferredRemoval = true;
11564                return;
11565            }
11566            if (DEBUG_DISPLAY) Slog.v(TAG, "Removing display=" + displayContent);
11567            mDisplayContents.delete(displayId);
11568            displayContent.close();
11569            if (displayId == Display.DEFAULT_DISPLAY) {
11570                unregisterPointerEventListener(displayContent.mTapDetector);
11571            }
11572        }
11573        mAnimator.removeDisplayLocked(displayId);
11574        requestTraversalLocked();
11575    }
11576
11577    public void onDisplayChanged(int displayId) {
11578        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0));
11579    }
11580
11581    private void handleDisplayChangedLocked(int displayId) {
11582        final DisplayContent displayContent = getDisplayContentLocked(displayId);
11583        if (displayContent != null) {
11584            displayContent.updateDisplayInfo();
11585        }
11586        requestTraversalLocked();
11587    }
11588
11589    @Override
11590    public Object getWindowManagerLock() {
11591        return mWindowMap;
11592    }
11593
11594    private final class LocalService extends WindowManagerInternal {
11595        @Override
11596        public void requestTraversalFromDisplayManager() {
11597            requestTraversal();
11598        }
11599
11600        @Override
11601        public void setMagnificationSpec(MagnificationSpec spec) {
11602            synchronized (mWindowMap) {
11603                if (mAccessibilityController != null) {
11604                    mAccessibilityController.setMagnificationSpecLocked(spec);
11605                } else {
11606                    throw new IllegalStateException("Magnification callbacks not set!");
11607                }
11608            }
11609            if (Binder.getCallingPid() != android.os.Process.myPid()) {
11610                spec.recycle();
11611            }
11612        }
11613
11614        @Override
11615        public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) {
11616            synchronized (mWindowMap) {
11617                WindowState windowState = mWindowMap.get(windowToken);
11618                if (windowState == null) {
11619                    return null;
11620                }
11621                MagnificationSpec spec = null;
11622                if (mAccessibilityController != null) {
11623                    spec = mAccessibilityController.getMagnificationSpecForWindowLocked(windowState);
11624                }
11625                if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) {
11626                    return null;
11627                }
11628                spec = (spec == null) ? MagnificationSpec.obtain() : MagnificationSpec.obtain(spec);
11629                spec.scale *= windowState.mGlobalScale;
11630                return spec;
11631            }
11632        }
11633
11634        @Override
11635        public void setMagnificationCallbacks(MagnificationCallbacks callbacks) {
11636            synchronized (mWindowMap) {
11637                if (mAccessibilityController == null) {
11638                    mAccessibilityController = new AccessibilityController(
11639                            WindowManagerService.this);
11640                }
11641                mAccessibilityController.setMagnificationCallbacksLocked(callbacks);
11642                if (!mAccessibilityController.hasCallbacksLocked()) {
11643                    mAccessibilityController = null;
11644                }
11645            }
11646        }
11647
11648        @Override
11649        public void setWindowsForAccessibilityCallback(WindowsForAccessibilityCallback callback) {
11650            synchronized (mWindowMap) {
11651                if (mAccessibilityController == null) {
11652                    mAccessibilityController = new AccessibilityController(
11653                            WindowManagerService.this);
11654                }
11655                mAccessibilityController.setWindowsForAccessibilityCallback(callback);
11656                if (!mAccessibilityController.hasCallbacksLocked()) {
11657                    mAccessibilityController = null;
11658                }
11659            }
11660        }
11661
11662        @Override
11663        public void setInputFilter(IInputFilter filter) {
11664            mInputManager.setInputFilter(filter);
11665        }
11666
11667        @Override
11668        public IBinder getFocusedWindowToken() {
11669            synchronized (mWindowMap) {
11670                WindowState windowState = getFocusedWindowLocked();
11671                if (windowState != null) {
11672                    return windowState.mClient.asBinder();
11673                }
11674                return null;
11675            }
11676        }
11677
11678        @Override
11679        public boolean isKeyguardLocked() {
11680            return WindowManagerService.this.isKeyguardLocked();
11681        }
11682
11683        @Override
11684        public void showGlobalActions() {
11685            WindowManagerService.this.showGlobalActions();
11686        }
11687
11688        @Override
11689        public void getWindowFrame(IBinder token, Rect outBounds) {
11690            synchronized (mWindowMap) {
11691                WindowState windowState = mWindowMap.get(token);
11692                if (windowState != null) {
11693                    outBounds.set(windowState.mFrame);
11694                } else {
11695                    outBounds.setEmpty();
11696                }
11697            }
11698        }
11699
11700        @Override
11701        public void waitForAllWindowsDrawn(Runnable callback, long timeout) {
11702            synchronized (mWindowMap) {
11703                mWaitingForDrawnCallback = callback;
11704                final WindowList windows = getDefaultWindowListLocked();
11705                for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
11706                    final WindowState win = windows.get(winNdx);
11707                    if (win.isVisibleLw()
11708                            && (win.mAppToken != null || mPolicy.isForceHiding(win.mAttrs))) {
11709                        win.mWinAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
11710                        // Force add to mResizingWindows.
11711                        win.mLastContentInsets.set(-1, -1, -1, -1);
11712                        mWaitingForDrawn.add(win);
11713                    }
11714                }
11715                requestTraversalLocked();
11716            }
11717            mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
11718            if (mWaitingForDrawn.isEmpty()) {
11719                callback.run();
11720            } else {
11721                mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout);
11722                checkDrawnWindowsLocked();
11723            }
11724        }
11725
11726        @Override
11727        public void addWindowToken(IBinder token, int type) {
11728            WindowManagerService.this.addWindowToken(token, type);
11729        }
11730
11731        @Override
11732        public void removeWindowToken(IBinder token, boolean removeWindows) {
11733            synchronized(mWindowMap) {
11734                if (removeWindows) {
11735                    WindowToken wtoken = mTokenMap.remove(token);
11736                    if (wtoken != null) {
11737                        wtoken.removeAllWindows();
11738                    }
11739                }
11740                WindowManagerService.this.removeWindowToken(token);
11741            }
11742        }
11743    }
11744}
11745