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