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