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