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