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