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