WindowManagerService.java revision 3de830b82b74f3df86ede47c8b1a0b8dcac113d6
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            AppTokenIterator iterator = displayContent.getTmpAppIterator(REVERSE_ITERATOR);
3128            for ( ; t >= 0; --t) {
3129                task = tasks.get(t);
3130                List<IApplicationToken> tokens = task.tokens;
3131                int v = task.tokens.size() - 1;
3132
3133                DisplayContent lastDisplayContent = displayContent;
3134                displayContent = mTaskIdToDisplayContents.get(taskId);
3135                if (displayContent != lastDisplayContent) {
3136                    Slog.w(TAG, "validateAppTokens: displayContent changed in TaskGroup list!");
3137                    return;
3138                }
3139
3140                while (v >= 0 && iterator.hasNext()) {
3141                    AppWindowToken atoken = iterator.next();
3142                    if (atoken.removed) {
3143                        continue;
3144                    }
3145                    if (tokens.get(v) != atoken.token) {
3146                        Slog.w(TAG, "Tokens out of sync: external is " + tokens.get(v)
3147                              + " @ " + v + ", internal is " + atoken.token);
3148                    }
3149                    v--;
3150                }
3151                while (v >= 0) {
3152                    Slog.w(TAG, "External token not found: " + tokens.get(v) + " @ " + v);
3153                    v--;
3154                }
3155            }
3156
3157            while (iterator.hasNext()) {
3158                AppWindowToken atoken = iterator.next();
3159                if (!atoken.removed) {
3160                    Slog.w(TAG, "Invalid internal atoken: " + atoken.token);
3161                }
3162            }
3163        }
3164    }
3165
3166    boolean checkCallingPermission(String permission, String func) {
3167        // Quick check: if the calling permission is me, it's all okay.
3168        if (Binder.getCallingPid() == Process.myPid()) {
3169            return true;
3170        }
3171
3172        if (mContext.checkCallingPermission(permission)
3173                == PackageManager.PERMISSION_GRANTED) {
3174            return true;
3175        }
3176        String msg = "Permission Denial: " + func + " from pid="
3177                + Binder.getCallingPid()
3178                + ", uid=" + Binder.getCallingUid()
3179                + " requires " + permission;
3180        Slog.w(TAG, msg);
3181        return false;
3182    }
3183
3184    boolean okToDisplay() {
3185        return !mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOnFully();
3186    }
3187
3188    AppWindowToken findAppWindowToken(IBinder token) {
3189        WindowToken wtoken = mTokenMap.get(token);
3190        if (wtoken == null) {
3191            return null;
3192        }
3193        return wtoken.appWindowToken;
3194    }
3195
3196    @Override
3197    public void addWindowToken(IBinder token, int type) {
3198        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3199                "addWindowToken()")) {
3200            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3201        }
3202
3203        synchronized(mWindowMap) {
3204            WindowToken wtoken = mTokenMap.get(token);
3205            if (wtoken != null) {
3206                Slog.w(TAG, "Attempted to add existing input method token: " + token);
3207                return;
3208            }
3209            wtoken = new WindowToken(this, token, type, true);
3210            mTokenMap.put(token, wtoken);
3211            if (type == TYPE_WALLPAPER) {
3212                mWallpaperTokens.add(wtoken);
3213            }
3214        }
3215    }
3216
3217    @Override
3218    public void removeWindowToken(IBinder token) {
3219        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3220                "removeWindowToken()")) {
3221            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3222        }
3223
3224        final long origId = Binder.clearCallingIdentity();
3225        synchronized(mWindowMap) {
3226            DisplayContent displayContent = null;
3227            WindowToken wtoken = mTokenMap.remove(token);
3228            if (wtoken != null) {
3229                boolean delayed = false;
3230                if (!wtoken.hidden) {
3231                    final int N = wtoken.windows.size();
3232                    boolean changed = false;
3233
3234                    for (int i=0; i<N; i++) {
3235                        WindowState win = wtoken.windows.get(i);
3236                        displayContent = win.mDisplayContent;
3237
3238                        if (win.mWinAnimator.isAnimating()) {
3239                            delayed = true;
3240                        }
3241
3242                        if (win.isVisibleNow()) {
3243                            win.mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_EXIT,
3244                                    false);
3245                            //TODO (multidisplay): Magnification is supported only for the default
3246                            if (mDisplayMagnifier != null && win.isDefaultDisplay()) {
3247                                mDisplayMagnifier.onWindowTransitionLocked(win,
3248                                        WindowManagerPolicy.TRANSIT_EXIT);
3249                            }
3250                            changed = true;
3251                            displayContent.layoutNeeded = true;
3252                        }
3253                    }
3254
3255                    wtoken.hidden = true;
3256
3257                    if (changed) {
3258                        performLayoutAndPlaceSurfacesLocked();
3259                        updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
3260                                false /*updateInputWindows*/);
3261                    }
3262
3263                    if (delayed) {
3264                        displayContent.mExitingTokens.add(wtoken);
3265                    } else if (wtoken.windowType == TYPE_WALLPAPER) {
3266                        mWallpaperTokens.remove(wtoken);
3267                    }
3268                }
3269
3270                mInputMonitor.updateInputWindowsLw(true /*force*/);
3271            } else {
3272                Slog.w(TAG, "Attempted to remove non-existing token: " + token);
3273            }
3274        }
3275        Binder.restoreCallingIdentity(origId);
3276    }
3277
3278    @Override
3279    public void addAppToken(int addPos, IApplicationToken token,
3280            int taskId, int requestedOrientation, boolean fullscreen, boolean showWhenLocked) {
3281        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3282                "addAppToken()")) {
3283            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3284        }
3285
3286        // Get the dispatching timeout here while we are not holding any locks so that it
3287        // can be cached by the AppWindowToken.  The timeout value is used later by the
3288        // input dispatcher in code that does hold locks.  If we did not cache the value
3289        // here we would run the chance of introducing a deadlock between the window manager
3290        // (which holds locks while updating the input dispatcher state) and the activity manager
3291        // (which holds locks while querying the application token).
3292        long inputDispatchingTimeoutNanos;
3293        try {
3294            inputDispatchingTimeoutNanos = token.getKeyDispatchingTimeout() * 1000000L;
3295        } catch (RemoteException ex) {
3296            Slog.w(TAG, "Could not get dispatching timeout.", ex);
3297            inputDispatchingTimeoutNanos = DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
3298        }
3299
3300        synchronized(mWindowMap) {
3301            AppWindowToken atoken = findAppWindowToken(token.asBinder());
3302            if (atoken != null) {
3303                Slog.w(TAG, "Attempted to add existing app token: " + token);
3304                return;
3305            }
3306            atoken = new AppWindowToken(this, token);
3307            atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
3308            atoken.groupId = taskId;
3309            atoken.appFullscreen = fullscreen;
3310            atoken.showWhenLocked = showWhenLocked;
3311            atoken.requestedOrientation = requestedOrientation;
3312            if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + atoken
3313                    + " at " + addPos);
3314
3315            DisplayContent displayContent = mTaskIdToDisplayContents.get(taskId);
3316            if (displayContent == null) {
3317                displayContent = getDefaultDisplayContentLocked();
3318                mTaskIdToDisplayContents.put(taskId, displayContent);
3319            }
3320            displayContent.addAppToken(addPos, atoken);
3321            mTokenMap.put(token.asBinder(), atoken);
3322            mTaskIdToDisplayContents.put(taskId, displayContent);
3323
3324            // Application tokens start out hidden.
3325            atoken.hidden = true;
3326            atoken.hiddenRequested = true;
3327
3328            //dump();
3329        }
3330    }
3331
3332    @Override
3333    public void setAppGroupId(IBinder token, int groupId) {
3334        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3335                "setAppGroupId()")) {
3336            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3337        }
3338
3339        synchronized(mWindowMap) {
3340            AppWindowToken atoken = findAppWindowToken(token);
3341            if (atoken == null) {
3342                Slog.w(TAG, "Attempted to set group id of non-existing app token: " + token);
3343                return;
3344            }
3345            mTaskIdToDisplayContents.get(atoken.groupId).setAppTaskId(atoken, groupId);
3346        }
3347    }
3348
3349    public int getOrientationFromWindowsLocked() {
3350        if (mDisplayFrozen || mOpeningApps.size() > 0 || mClosingApps.size() > 0) {
3351            // If the display is frozen, some activities may be in the middle
3352            // of restarting, and thus have removed their old window.  If the
3353            // window has the flag to hide the lock screen, then the lock screen
3354            // can re-appear and inflict its own orientation on us.  Keep the
3355            // orientation stable until this all settles down.
3356            return mLastWindowForcedOrientation;
3357        }
3358
3359        // TODO(multidisplay): Change to the correct display.
3360        final WindowList windows = getDefaultWindowListLocked();
3361        int pos = windows.size() - 1;
3362        while (pos >= 0) {
3363            WindowState win = windows.get(pos);
3364            pos--;
3365            if (win.mAppToken != null) {
3366                // We hit an application window. so the orientation will be determined by the
3367                // app window. No point in continuing further.
3368                return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
3369            }
3370            if (!win.isVisibleLw() || !win.mPolicyVisibilityAfterAnim) {
3371                continue;
3372            }
3373            int req = win.mAttrs.screenOrientation;
3374            if((req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) ||
3375                    (req == ActivityInfo.SCREEN_ORIENTATION_BEHIND)){
3376                continue;
3377            }
3378
3379            if (DEBUG_ORIENTATION) Slog.v(TAG, win + " forcing orientation to " + req);
3380            return (mLastWindowForcedOrientation=req);
3381        }
3382        return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
3383    }
3384
3385    public int getOrientationFromAppTokensLocked() {
3386        int curGroup = 0;
3387        int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3388        boolean findingBehind = false;
3389        boolean haveGroup = false;
3390        boolean lastFullscreen = false;
3391        // TODO: Multi window.
3392        DisplayContent displayContent = getDefaultDisplayContentLocked();
3393        AppTokenIterator iterator = displayContent.getTmpAppIterator(REVERSE_ITERATOR);
3394        while (iterator.hasNext()) {
3395            AppWindowToken atoken = iterator.next();
3396
3397            if (DEBUG_APP_ORIENTATION) Slog.v(TAG, "Checking app orientation: " + atoken);
3398
3399            // if we're about to tear down this window and not seek for
3400            // the behind activity, don't use it for orientation
3401            if (!findingBehind
3402                    && (!atoken.hidden && atoken.hiddenRequested)) {
3403                if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken
3404                        + " -- going to hide");
3405                continue;
3406            }
3407
3408            if (haveGroup == true && curGroup != atoken.groupId) {
3409                // If we have hit a new application group, and the bottom
3410                // of the previous group didn't explicitly say to use
3411                // the orientation behind it, and the last app was
3412                // full screen, then we'll stick with the
3413                // user's orientation.
3414                if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND
3415                        && lastFullscreen) {
3416                    if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
3417                            + " -- end of group, return " + lastOrientation);
3418                    return lastOrientation;
3419                }
3420            }
3421
3422            // We ignore any hidden applications on the top.
3423            if (atoken.hiddenRequested || atoken.willBeHidden) {
3424                if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken
3425                        + " -- hidden on top");
3426                continue;
3427            }
3428
3429            if (!haveGroup) {
3430                haveGroup = true;
3431                curGroup = atoken.groupId;
3432                lastOrientation = atoken.requestedOrientation;
3433            }
3434
3435            int or = atoken.requestedOrientation;
3436            // If this application is fullscreen, and didn't explicitly say
3437            // to use the orientation behind it, then just take whatever
3438            // orientation it has and ignores whatever is under it.
3439            lastFullscreen = atoken.appFullscreen;
3440            if (lastFullscreen
3441                    && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
3442                if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
3443                        + " -- full screen, return " + or);
3444                return or;
3445            }
3446            // If this application has requested an explicit orientation,
3447            // then use it.
3448            if (or != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
3449                    && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
3450                if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
3451                        + " -- explicitly set, return " + or);
3452                return or;
3453            }
3454            findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND);
3455        }
3456        if (DEBUG_ORIENTATION) Slog.v(TAG, "No app is requesting an orientation");
3457        return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3458    }
3459
3460    @Override
3461    public Configuration updateOrientationFromAppTokens(
3462            Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
3463        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3464                "updateOrientationFromAppTokens()")) {
3465            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3466        }
3467
3468        Configuration config = null;
3469        long ident = Binder.clearCallingIdentity();
3470
3471        synchronized(mWindowMap) {
3472            config = updateOrientationFromAppTokensLocked(currentConfig,
3473                    freezeThisOneIfNeeded);
3474        }
3475
3476        Binder.restoreCallingIdentity(ident);
3477        return config;
3478    }
3479
3480    private Configuration updateOrientationFromAppTokensLocked(
3481            Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
3482        Configuration config = null;
3483
3484        if (updateOrientationFromAppTokensLocked(false)) {
3485            if (freezeThisOneIfNeeded != null) {
3486                AppWindowToken atoken = findAppWindowToken(freezeThisOneIfNeeded);
3487                if (atoken != null) {
3488                    startAppFreezingScreenLocked(atoken, ActivityInfo.CONFIG_ORIENTATION);
3489                }
3490            }
3491            config = computeNewConfigurationLocked();
3492
3493        } else if (currentConfig != null) {
3494            // No obvious action we need to take, but if our current
3495            // state mismatches the activity manager's, update it,
3496            // disregarding font scale, which should remain set to
3497            // the value of the previous configuration.
3498            mTempConfiguration.setToDefaults();
3499            mTempConfiguration.fontScale = currentConfig.fontScale;
3500            if (computeScreenConfigurationLocked(mTempConfiguration)) {
3501                if (currentConfig.diff(mTempConfiguration) != 0) {
3502                    mWaitingForConfig = true;
3503                    getDefaultDisplayContentLocked().layoutNeeded = true;
3504                    startFreezingDisplayLocked(false, 0, 0);
3505                    config = new Configuration(mTempConfiguration);
3506                }
3507            }
3508        }
3509
3510        return config;
3511    }
3512
3513    /*
3514     * Determine the new desired orientation of the display, returning
3515     * a non-null new Configuration if it has changed from the current
3516     * orientation.  IF TRUE IS RETURNED SOMEONE MUST CALL
3517     * setNewConfiguration() TO TELL THE WINDOW MANAGER IT CAN UNFREEZE THE
3518     * SCREEN.  This will typically be done for you if you call
3519     * sendNewConfiguration().
3520     *
3521     * The orientation is computed from non-application windows first. If none of
3522     * the non-application windows specify orientation, the orientation is computed from
3523     * application tokens.
3524     * @see android.view.IWindowManager#updateOrientationFromAppTokens(
3525     * android.os.IBinder)
3526     */
3527    boolean updateOrientationFromAppTokensLocked(boolean inTransaction) {
3528        long ident = Binder.clearCallingIdentity();
3529        try {
3530            int req = getOrientationFromWindowsLocked();
3531            if (req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
3532                req = getOrientationFromAppTokensLocked();
3533            }
3534
3535            if (req != mForcedAppOrientation) {
3536                mForcedAppOrientation = req;
3537                //send a message to Policy indicating orientation change to take
3538                //action like disabling/enabling sensors etc.,
3539                mPolicy.setCurrentOrientationLw(req);
3540                if (updateRotationUncheckedLocked(inTransaction)) {
3541                    // changed
3542                    return true;
3543                }
3544            }
3545
3546            return false;
3547        } finally {
3548            Binder.restoreCallingIdentity(ident);
3549        }
3550    }
3551
3552    @Override
3553    public void setNewConfiguration(Configuration config) {
3554        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3555                "setNewConfiguration()")) {
3556            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3557        }
3558
3559        synchronized(mWindowMap) {
3560            mCurConfiguration = new Configuration(config);
3561            mWaitingForConfig = false;
3562            performLayoutAndPlaceSurfacesLocked();
3563        }
3564    }
3565
3566    @Override
3567    public void setAppOrientation(IApplicationToken token, int requestedOrientation) {
3568        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3569                "setAppOrientation()")) {
3570            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3571        }
3572
3573        synchronized(mWindowMap) {
3574            AppWindowToken atoken = findAppWindowToken(token.asBinder());
3575            if (atoken == null) {
3576                Slog.w(TAG, "Attempted to set orientation of non-existing app token: " + token);
3577                return;
3578            }
3579
3580            atoken.requestedOrientation = requestedOrientation;
3581        }
3582    }
3583
3584    @Override
3585    public int getAppOrientation(IApplicationToken token) {
3586        synchronized(mWindowMap) {
3587            AppWindowToken wtoken = findAppWindowToken(token.asBinder());
3588            if (wtoken == null) {
3589                return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3590            }
3591
3592            return wtoken.requestedOrientation;
3593        }
3594    }
3595
3596    @Override
3597    public void setFocusedApp(IBinder token, boolean moveFocusNow) {
3598        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3599                "setFocusedApp()")) {
3600            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3601        }
3602
3603        synchronized(mWindowMap) {
3604            boolean changed = false;
3605            if (token == null) {
3606                if (DEBUG_FOCUS) Slog.v(TAG, "Clearing focused app, was " + mFocusedApp);
3607                changed = mFocusedApp != null;
3608                mFocusedApp = null;
3609                if (changed) {
3610                    mInputMonitor.setFocusedAppLw(null);
3611                }
3612            } else {
3613                AppWindowToken newFocus = findAppWindowToken(token);
3614                if (newFocus == null) {
3615                    Slog.w(TAG, "Attempted to set focus to non-existing app token: " + token);
3616                    return;
3617                }
3618                changed = mFocusedApp != newFocus;
3619                mFocusedApp = newFocus;
3620                if (DEBUG_FOCUS) Slog.v(TAG, "Set focused app to: " + mFocusedApp
3621                        + " moveFocusNow=" + moveFocusNow);
3622                if (changed) {
3623                    mInputMonitor.setFocusedAppLw(newFocus);
3624                }
3625            }
3626
3627            if (moveFocusNow && changed) {
3628                final long origId = Binder.clearCallingIdentity();
3629                updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
3630                Binder.restoreCallingIdentity(origId);
3631            }
3632        }
3633    }
3634
3635    @Override
3636    public void prepareAppTransition(int transit, boolean alwaysKeepCurrent) {
3637        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3638                "prepareAppTransition()")) {
3639            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3640        }
3641
3642        synchronized(mWindowMap) {
3643            if (DEBUG_APP_TRANSITIONS) Slog.v(
3644                    TAG, "Prepare app transition: transit=" + transit
3645                    + " " + mAppTransition
3646                    + " alwaysKeepCurrent=" + alwaysKeepCurrent
3647                    + " Callers=" + Debug.getCallers(3));
3648            if (okToDisplay()) {
3649                if (!mAppTransition.isTransitionSet() || mAppTransition.isTransitionNone()) {
3650                    mAppTransition.setAppTransition(transit);
3651                } else if (!alwaysKeepCurrent) {
3652                    if (transit == AppTransition.TRANSIT_TASK_OPEN
3653                            && mAppTransition.isTransitionEqual(
3654                                    AppTransition.TRANSIT_TASK_CLOSE)) {
3655                        // Opening a new task always supersedes a close for the anim.
3656                        mAppTransition.setAppTransition(transit);
3657                    } else if (transit == AppTransition.TRANSIT_ACTIVITY_OPEN
3658                            && mAppTransition.isTransitionEqual(
3659                                AppTransition.TRANSIT_ACTIVITY_CLOSE)) {
3660                        // Opening a new activity always supersedes a close for the anim.
3661                        mAppTransition.setAppTransition(transit);
3662                    }
3663                }
3664                mAppTransition.prepare();
3665                mStartingIconInTransition = false;
3666                mSkipAppTransitionAnimation = false;
3667                mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
3668                mH.sendEmptyMessageDelayed(H.APP_TRANSITION_TIMEOUT, 5000);
3669            }
3670        }
3671    }
3672
3673    @Override
3674    public int getPendingAppTransition() {
3675        return mAppTransition.getAppTransition();
3676    }
3677
3678    @Override
3679    public void overridePendingAppTransition(String packageName,
3680            int enterAnim, int exitAnim, IRemoteCallback startedCallback) {
3681        synchronized(mWindowMap) {
3682            mAppTransition.overridePendingAppTransition(packageName, enterAnim, exitAnim,
3683                    startedCallback);
3684        }
3685    }
3686
3687    @Override
3688    public void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
3689            int startHeight) {
3690        synchronized(mWindowMap) {
3691            mAppTransition.overridePendingAppTransitionScaleUp(startX, startY, startWidth,
3692                    startHeight);
3693        }
3694    }
3695
3696    @Override
3697    public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX,
3698            int startY, IRemoteCallback startedCallback, boolean scaleUp) {
3699        synchronized(mWindowMap) {
3700            mAppTransition.overridePendingAppTransitionThumb(srcThumb, startX, startY,
3701                    startedCallback, scaleUp);
3702        }
3703    }
3704
3705    @Override
3706    public void executeAppTransition() {
3707        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3708                "executeAppTransition()")) {
3709            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3710        }
3711
3712        synchronized(mWindowMap) {
3713            if (DEBUG_APP_TRANSITIONS) {
3714                RuntimeException e = new RuntimeException("here");
3715                e.fillInStackTrace();
3716                Slog.w(TAG, "Execute app transition: " + mAppTransition, e);
3717            }
3718            if (mAppTransition.isTransitionSet()) {
3719                mAppTransition.setReady();
3720                final long origId = Binder.clearCallingIdentity();
3721                performLayoutAndPlaceSurfacesLocked();
3722                Binder.restoreCallingIdentity(origId);
3723            }
3724        }
3725    }
3726
3727    @Override
3728    public void setAppStartingWindow(IBinder token, String pkg,
3729            int theme, CompatibilityInfo compatInfo,
3730            CharSequence nonLocalizedLabel, int labelRes, int icon,
3731            int windowFlags, IBinder transferFrom, boolean createIfNeeded) {
3732        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3733                "setAppStartingWindow()")) {
3734            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3735        }
3736
3737        synchronized(mWindowMap) {
3738            if (DEBUG_STARTING_WINDOW) Slog.v(
3739                    TAG, "setAppStartingWindow: token=" + token + " pkg=" + pkg
3740                    + " transferFrom=" + transferFrom);
3741
3742            AppWindowToken wtoken = findAppWindowToken(token);
3743            if (wtoken == null) {
3744                Slog.w(TAG, "Attempted to set icon of non-existing app token: " + token);
3745                return;
3746            }
3747
3748            // If the display is frozen, we won't do anything until the
3749            // actual window is displayed so there is no reason to put in
3750            // the starting window.
3751            if (!okToDisplay()) {
3752                return;
3753            }
3754
3755            if (wtoken.startingData != null) {
3756                return;
3757            }
3758
3759            if (transferFrom != null) {
3760                AppWindowToken ttoken = findAppWindowToken(transferFrom);
3761                if (ttoken != null) {
3762                    WindowState startingWindow = ttoken.startingWindow;
3763                    if (startingWindow != null) {
3764                        if (mStartingIconInTransition) {
3765                            // In this case, the starting icon has already
3766                            // been displayed, so start letting windows get
3767                            // shown immediately without any more transitions.
3768                            mSkipAppTransitionAnimation = true;
3769                        }
3770                        if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
3771                                "Moving existing starting " + startingWindow + " from " + ttoken
3772                                + " to " + wtoken);
3773                        final long origId = Binder.clearCallingIdentity();
3774
3775                        // Transfer the starting window over to the new
3776                        // token.
3777                        wtoken.startingData = ttoken.startingData;
3778                        wtoken.startingView = ttoken.startingView;
3779                        wtoken.startingDisplayed = ttoken.startingDisplayed;
3780                        ttoken.startingDisplayed = false;
3781                        wtoken.startingWindow = startingWindow;
3782                        wtoken.reportedVisible = ttoken.reportedVisible;
3783                        ttoken.startingData = null;
3784                        ttoken.startingView = null;
3785                        ttoken.startingWindow = null;
3786                        ttoken.startingMoved = true;
3787                        startingWindow.mToken = wtoken;
3788                        startingWindow.mRootToken = wtoken;
3789                        startingWindow.mAppToken = wtoken;
3790                        startingWindow.mWinAnimator.mAppAnimator = wtoken.mAppAnimator;
3791
3792                        if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) {
3793                            Slog.v(TAG, "Removing starting window: " + startingWindow);
3794                        }
3795                        startingWindow.getWindowList().remove(startingWindow);
3796                        mWindowsChanged = true;
3797                        if (DEBUG_ADD_REMOVE) Slog.v(TAG,
3798                                "Removing starting " + startingWindow + " from " + ttoken);
3799                        ttoken.windows.remove(startingWindow);
3800                        ttoken.allAppWindows.remove(startingWindow);
3801                        addWindowToListInOrderLocked(startingWindow, true);
3802
3803                        // Propagate other interesting state between the
3804                        // tokens.  If the old token is displayed, we should
3805                        // immediately force the new one to be displayed.  If
3806                        // it is animating, we need to move that animation to
3807                        // the new one.
3808                        if (ttoken.allDrawn) {
3809                            wtoken.allDrawn = true;
3810                            wtoken.deferClearAllDrawn = ttoken.deferClearAllDrawn;
3811                        }
3812                        if (ttoken.firstWindowDrawn) {
3813                            wtoken.firstWindowDrawn = true;
3814                        }
3815                        if (!ttoken.hidden) {
3816                            wtoken.hidden = false;
3817                            wtoken.hiddenRequested = false;
3818                            wtoken.willBeHidden = false;
3819                        }
3820                        if (wtoken.clientHidden != ttoken.clientHidden) {
3821                            wtoken.clientHidden = ttoken.clientHidden;
3822                            wtoken.sendAppVisibilityToClients();
3823                        }
3824                        final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator;
3825                        final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator;
3826                        if (tAppAnimator.animation != null) {
3827                            wAppAnimator.animation = tAppAnimator.animation;
3828                            wAppAnimator.animating = tAppAnimator.animating;
3829                            wAppAnimator.animLayerAdjustment = tAppAnimator.animLayerAdjustment;
3830                            tAppAnimator.animation = null;
3831                            tAppAnimator.animLayerAdjustment = 0;
3832                            wAppAnimator.updateLayers();
3833                            tAppAnimator.updateLayers();
3834                        }
3835
3836                        updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
3837                                true /*updateInputWindows*/);
3838                        getDefaultDisplayContentLocked().layoutNeeded = true;
3839                        performLayoutAndPlaceSurfacesLocked();
3840                        Binder.restoreCallingIdentity(origId);
3841                        return;
3842                    } else if (ttoken.startingData != null) {
3843                        // The previous app was getting ready to show a
3844                        // starting window, but hasn't yet done so.  Steal it!
3845                        if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
3846                                "Moving pending starting from " + ttoken
3847                                + " to " + wtoken);
3848                        wtoken.startingData = ttoken.startingData;
3849                        ttoken.startingData = null;
3850                        ttoken.startingMoved = true;
3851                        Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
3852                        // Note: we really want to do sendMessageAtFrontOfQueue() because we
3853                        // want to process the message ASAP, before any other queued
3854                        // messages.
3855                        mH.sendMessageAtFrontOfQueue(m);
3856                        return;
3857                    }
3858                    final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator;
3859                    final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator;
3860                    if (tAppAnimator.thumbnail != null) {
3861                        // The old token is animating with a thumbnail, transfer
3862                        // that to the new token.
3863                        if (wAppAnimator.thumbnail != null) {
3864                            wAppAnimator.thumbnail.destroy();
3865                        }
3866                        wAppAnimator.thumbnail = tAppAnimator.thumbnail;
3867                        wAppAnimator.thumbnailX = tAppAnimator.thumbnailX;
3868                        wAppAnimator.thumbnailY = tAppAnimator.thumbnailY;
3869                        wAppAnimator.thumbnailLayer = tAppAnimator.thumbnailLayer;
3870                        wAppAnimator.thumbnailAnimation = tAppAnimator.thumbnailAnimation;
3871                        tAppAnimator.thumbnail = null;
3872                    }
3873                }
3874            }
3875
3876            // There is no existing starting window, and the caller doesn't
3877            // want us to create one, so that's it!
3878            if (!createIfNeeded) {
3879                return;
3880            }
3881
3882            // If this is a translucent window, then don't
3883            // show a starting window -- the current effect (a full-screen
3884            // opaque starting window that fades away to the real contents
3885            // when it is ready) does not work for this.
3886            if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Checking theme of starting window: 0x"
3887                    + Integer.toHexString(theme));
3888            if (theme != 0) {
3889                AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
3890                        com.android.internal.R.styleable.Window);
3891                if (ent == null) {
3892                    // Whoops!  App doesn't exist.  Um.  Okay.  We'll just
3893                    // pretend like we didn't see that.
3894                    return;
3895                }
3896                if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Translucent="
3897                        + ent.array.getBoolean(
3898                                com.android.internal.R.styleable.Window_windowIsTranslucent, false)
3899                        + " Floating="
3900                        + ent.array.getBoolean(
3901                                com.android.internal.R.styleable.Window_windowIsFloating, false)
3902                        + " ShowWallpaper="
3903                        + ent.array.getBoolean(
3904                                com.android.internal.R.styleable.Window_windowShowWallpaper, false));
3905                if (ent.array.getBoolean(
3906                        com.android.internal.R.styleable.Window_windowIsTranslucent, false)) {
3907                    return;
3908                }
3909                if (ent.array.getBoolean(
3910                        com.android.internal.R.styleable.Window_windowIsFloating, false)) {
3911                    return;
3912                }
3913                if (ent.array.getBoolean(
3914                        com.android.internal.R.styleable.Window_windowShowWallpaper, false)) {
3915                    if (mWallpaperTarget == null) {
3916                        // If this theme is requesting a wallpaper, and the wallpaper
3917                        // is not curently visible, then this effectively serves as
3918                        // an opaque window and our starting window transition animation
3919                        // can still work.  We just need to make sure the starting window
3920                        // is also showing the wallpaper.
3921                        windowFlags |= FLAG_SHOW_WALLPAPER;
3922                    } else {
3923                        return;
3924                    }
3925                }
3926            }
3927
3928            if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Creating StartingData");
3929            mStartingIconInTransition = true;
3930            wtoken.startingData = new StartingData(pkg, theme, compatInfo, nonLocalizedLabel,
3931                    labelRes, icon, windowFlags);
3932            Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
3933            // Note: we really want to do sendMessageAtFrontOfQueue() because we
3934            // want to process the message ASAP, before any other queued
3935            // messages.
3936            if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Enqueueing ADD_STARTING");
3937            mH.sendMessageAtFrontOfQueue(m);
3938        }
3939    }
3940
3941    @Override
3942    public void setAppWillBeHidden(IBinder token) {
3943        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3944                "setAppWillBeHidden()")) {
3945            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3946        }
3947
3948        AppWindowToken wtoken;
3949
3950        synchronized(mWindowMap) {
3951            wtoken = findAppWindowToken(token);
3952            if (wtoken == null) {
3953                Slog.w(TAG, "Attempted to set will be hidden of non-existing app token: " + token);
3954                return;
3955            }
3956            wtoken.willBeHidden = true;
3957        }
3958    }
3959
3960    boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp,
3961            boolean visible, int transit, boolean performLayout) {
3962        boolean delayed = false;
3963
3964        if (wtoken.clientHidden == visible) {
3965            wtoken.clientHidden = !visible;
3966            wtoken.sendAppVisibilityToClients();
3967        }
3968
3969        wtoken.willBeHidden = false;
3970        if (wtoken.hidden == visible) {
3971            boolean changed = false;
3972            if (DEBUG_APP_TRANSITIONS) Slog.v(
3973                TAG, "Changing app " + wtoken + " hidden=" + wtoken.hidden
3974                + " performLayout=" + performLayout);
3975
3976            boolean runningAppAnimation = false;
3977
3978            if (transit != AppTransition.TRANSIT_UNSET) {
3979                if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) {
3980                    wtoken.mAppAnimator.animation = null;
3981                }
3982                if (applyAnimationLocked(wtoken, lp, transit, visible)) {
3983                    delayed = runningAppAnimation = true;
3984                }
3985                WindowState window = wtoken.findMainWindow();
3986                //TODO (multidisplay): Magnification is supported only for the default display.
3987                if (window != null && mDisplayMagnifier != null
3988                        && window.getDisplayId() == Display.DEFAULT_DISPLAY) {
3989                    mDisplayMagnifier.onAppWindowTransitionLocked(window, transit);
3990                }
3991                changed = true;
3992            }
3993
3994            final int N = wtoken.allAppWindows.size();
3995            for (int i=0; i<N; i++) {
3996                WindowState win = wtoken.allAppWindows.get(i);
3997                if (win == wtoken.startingWindow) {
3998                    continue;
3999                }
4000
4001                //Slog.i(TAG, "Window " + win + ": vis=" + win.isVisible());
4002                //win.dump("  ");
4003                if (visible) {
4004                    if (!win.isVisibleNow()) {
4005                        if (!runningAppAnimation) {
4006                            win.mWinAnimator.applyAnimationLocked(
4007                                    WindowManagerPolicy.TRANSIT_ENTER, true);
4008                            //TODO (multidisplay): Magnification is supported only for the default
4009                            if (mDisplayMagnifier != null
4010                                    && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
4011                                mDisplayMagnifier.onWindowTransitionLocked(win,
4012                                        WindowManagerPolicy.TRANSIT_ENTER);
4013                            }
4014                        }
4015                        changed = true;
4016                        win.mDisplayContent.layoutNeeded = true;
4017                    }
4018                } else if (win.isVisibleNow()) {
4019                    if (!runningAppAnimation) {
4020                        win.mWinAnimator.applyAnimationLocked(
4021                                WindowManagerPolicy.TRANSIT_EXIT, false);
4022                        //TODO (multidisplay): Magnification is supported only for the default
4023                        if (mDisplayMagnifier != null
4024                                && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
4025                            mDisplayMagnifier.onWindowTransitionLocked(win,
4026                                    WindowManagerPolicy.TRANSIT_EXIT);
4027                        }
4028                    }
4029                    changed = true;
4030                    win.mDisplayContent.layoutNeeded = true;
4031                }
4032            }
4033
4034            wtoken.hidden = wtoken.hiddenRequested = !visible;
4035            if (!visible) {
4036                unsetAppFreezingScreenLocked(wtoken, true, true);
4037            } else {
4038                // If we are being set visible, and the starting window is
4039                // not yet displayed, then make sure it doesn't get displayed.
4040                WindowState swin = wtoken.startingWindow;
4041                if (swin != null && !swin.isDrawnLw()) {
4042                    swin.mPolicyVisibility = false;
4043                    swin.mPolicyVisibilityAfterAnim = false;
4044                 }
4045            }
4046
4047            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "setTokenVisibilityLocked: " + wtoken
4048                      + ": hidden=" + wtoken.hidden + " hiddenRequested="
4049                      + wtoken.hiddenRequested);
4050
4051            if (changed) {
4052                mInputMonitor.setUpdateInputWindowsNeededLw();
4053                if (performLayout) {
4054                    updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
4055                            false /*updateInputWindows*/);
4056                    performLayoutAndPlaceSurfacesLocked();
4057                }
4058                mInputMonitor.updateInputWindowsLw(false /*force*/);
4059            }
4060        }
4061
4062        if (wtoken.mAppAnimator.animation != null) {
4063            delayed = true;
4064        }
4065
4066        for (int i = wtoken.allAppWindows.size() - 1; i >= 0 && !delayed; i--) {
4067            if (wtoken.allAppWindows.get(i).mWinAnimator.isWindowAnimating()) {
4068                delayed = true;
4069            }
4070        }
4071
4072        return delayed;
4073    }
4074
4075    @Override
4076    public void setAppVisibility(IBinder token, boolean visible) {
4077        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4078                "setAppVisibility()")) {
4079            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4080        }
4081
4082        AppWindowToken wtoken;
4083
4084        synchronized(mWindowMap) {
4085            wtoken = findAppWindowToken(token);
4086            if (wtoken == null) {
4087                Slog.w(TAG, "Attempted to set visibility of non-existing app token: " + token);
4088                return;
4089            }
4090
4091            if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) {
4092                RuntimeException e = null;
4093                if (!HIDE_STACK_CRAWLS) {
4094                    e = new RuntimeException();
4095                    e.fillInStackTrace();
4096                }
4097                Slog.v(TAG, "setAppVisibility(" + token + ", visible=" + visible
4098                        + "): " + mAppTransition
4099                        + " hidden=" + wtoken.hidden
4100                        + " hiddenRequested=" + wtoken.hiddenRequested, e);
4101            }
4102
4103            // If we are preparing an app transition, then delay changing
4104            // the visibility of this token until we execute that transition.
4105            if (okToDisplay() && mAppTransition.isTransitionSet()) {
4106                // Already in requested state, don't do anything more.
4107                if (wtoken.hiddenRequested != visible) {
4108                    return;
4109                }
4110                wtoken.hiddenRequested = !visible;
4111
4112                if (!wtoken.startingDisplayed) {
4113                    if (DEBUG_APP_TRANSITIONS) Slog.v(
4114                            TAG, "Setting dummy animation on: " + wtoken);
4115                    wtoken.mAppAnimator.setDummyAnimation();
4116                }
4117                mOpeningApps.remove(wtoken);
4118                mClosingApps.remove(wtoken);
4119                wtoken.waitingToShow = wtoken.waitingToHide = false;
4120                wtoken.inPendingTransaction = true;
4121                if (visible) {
4122                    mOpeningApps.add(wtoken);
4123                    wtoken.startingMoved = false;
4124
4125                    // If the token is currently hidden (should be the
4126                    // common case), then we need to set up to wait for
4127                    // its windows to be ready.
4128                    if (wtoken.hidden) {
4129                        wtoken.allDrawn = false;
4130                        wtoken.deferClearAllDrawn = false;
4131                        wtoken.waitingToShow = true;
4132
4133                        if (wtoken.clientHidden) {
4134                            // In the case where we are making an app visible
4135                            // but holding off for a transition, we still need
4136                            // to tell the client to make its windows visible so
4137                            // they get drawn.  Otherwise, we will wait on
4138                            // performing the transition until all windows have
4139                            // been drawn, they never will be, and we are sad.
4140                            wtoken.clientHidden = false;
4141                            wtoken.sendAppVisibilityToClients();
4142                        }
4143                    }
4144                } else {
4145                    mClosingApps.add(wtoken);
4146
4147                    // If the token is currently visible (should be the
4148                    // common case), then set up to wait for it to be hidden.
4149                    if (!wtoken.hidden) {
4150                        wtoken.waitingToHide = true;
4151                    }
4152                }
4153                return;
4154            }
4155
4156            final long origId = Binder.clearCallingIdentity();
4157            setTokenVisibilityLocked(wtoken, null, visible, AppTransition.TRANSIT_UNSET,
4158                    true);
4159            wtoken.updateReportedVisibilityLocked();
4160            Binder.restoreCallingIdentity(origId);
4161        }
4162    }
4163
4164    void unsetAppFreezingScreenLocked(AppWindowToken wtoken,
4165            boolean unfreezeSurfaceNow, boolean force) {
4166        if (wtoken.mAppAnimator.freezingScreen) {
4167            if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + wtoken
4168                    + " force=" + force);
4169            final int N = wtoken.allAppWindows.size();
4170            boolean unfrozeWindows = false;
4171            for (int i=0; i<N; i++) {
4172                WindowState w = wtoken.allAppWindows.get(i);
4173                if (w.mAppFreezing) {
4174                    w.mAppFreezing = false;
4175                    if (w.mHasSurface && !w.mOrientationChanging) {
4176                        if (DEBUG_ORIENTATION) Slog.v(TAG, "set mOrientationChanging of " + w);
4177                        w.mOrientationChanging = true;
4178                        mInnerFields.mOrientationChangeComplete = false;
4179                    }
4180                    unfrozeWindows = true;
4181                    w.mDisplayContent.layoutNeeded = true;
4182                }
4183            }
4184            if (force || unfrozeWindows) {
4185                if (DEBUG_ORIENTATION) Slog.v(TAG, "No longer freezing: " + wtoken);
4186                wtoken.mAppAnimator.freezingScreen = false;
4187                mAppsFreezingScreen--;
4188            }
4189            if (unfreezeSurfaceNow) {
4190                if (unfrozeWindows) {
4191                    performLayoutAndPlaceSurfacesLocked();
4192                }
4193                stopFreezingDisplayLocked();
4194            }
4195        }
4196    }
4197
4198    public void startAppFreezingScreenLocked(AppWindowToken wtoken,
4199            int configChanges) {
4200        if (DEBUG_ORIENTATION) {
4201            RuntimeException e = null;
4202            if (!HIDE_STACK_CRAWLS) {
4203                e = new RuntimeException();
4204                e.fillInStackTrace();
4205            }
4206            Slog.i(TAG, "Set freezing of " + wtoken.appToken
4207                    + ": hidden=" + wtoken.hidden + " freezing="
4208                    + wtoken.mAppAnimator.freezingScreen, e);
4209        }
4210        if (!wtoken.hiddenRequested) {
4211            if (!wtoken.mAppAnimator.freezingScreen) {
4212                wtoken.mAppAnimator.freezingScreen = true;
4213                mAppsFreezingScreen++;
4214                if (mAppsFreezingScreen == 1) {
4215                    startFreezingDisplayLocked(false, 0, 0);
4216                    mH.removeMessages(H.APP_FREEZE_TIMEOUT);
4217                    mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 5000);
4218                }
4219            }
4220            final int N = wtoken.allAppWindows.size();
4221            for (int i=0; i<N; i++) {
4222                WindowState w = wtoken.allAppWindows.get(i);
4223                w.mAppFreezing = true;
4224            }
4225        }
4226    }
4227
4228    @Override
4229    public void startAppFreezingScreen(IBinder token, int configChanges) {
4230        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4231                "setAppFreezingScreen()")) {
4232            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4233        }
4234
4235        synchronized(mWindowMap) {
4236            if (configChanges == 0 && okToDisplay()) {
4237                if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping set freeze of " + token);
4238                return;
4239            }
4240
4241            AppWindowToken wtoken = findAppWindowToken(token);
4242            if (wtoken == null || wtoken.appToken == null) {
4243                Slog.w(TAG, "Attempted to freeze screen with non-existing app token: " + wtoken);
4244                return;
4245            }
4246            final long origId = Binder.clearCallingIdentity();
4247            startAppFreezingScreenLocked(wtoken, configChanges);
4248            Binder.restoreCallingIdentity(origId);
4249        }
4250    }
4251
4252    @Override
4253    public void stopAppFreezingScreen(IBinder token, boolean force) {
4254        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4255                "setAppFreezingScreen()")) {
4256            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4257        }
4258
4259        synchronized(mWindowMap) {
4260            AppWindowToken wtoken = findAppWindowToken(token);
4261            if (wtoken == null || wtoken.appToken == null) {
4262                return;
4263            }
4264            final long origId = Binder.clearCallingIdentity();
4265            if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + token
4266                    + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.mAppAnimator.freezingScreen);
4267            unsetAppFreezingScreenLocked(wtoken, true, force);
4268            Binder.restoreCallingIdentity(origId);
4269        }
4270    }
4271
4272    @Override
4273    public void removeAppToken(IBinder token) {
4274        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4275                "removeAppToken()")) {
4276            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4277        }
4278
4279        AppWindowToken wtoken = null;
4280        AppWindowToken startingToken = null;
4281        boolean delayed = false;
4282
4283        final long origId = Binder.clearCallingIdentity();
4284        synchronized(mWindowMap) {
4285            WindowToken basewtoken = mTokenMap.remove(token);
4286            if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) {
4287                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Removing app token: " + wtoken);
4288                delayed = setTokenVisibilityLocked(wtoken, null, false,
4289                        AppTransition.TRANSIT_UNSET, true);
4290                wtoken.inPendingTransaction = false;
4291                mOpeningApps.remove(wtoken);
4292                wtoken.waitingToShow = false;
4293                if (mClosingApps.contains(wtoken)) {
4294                    delayed = true;
4295                } else if (mAppTransition.isTransitionSet()) {
4296                    mClosingApps.add(wtoken);
4297                    wtoken.waitingToHide = true;
4298                    delayed = true;
4299                }
4300                if (DEBUG_APP_TRANSITIONS) Slog.v(
4301                        TAG, "Removing app " + wtoken + " delayed=" + delayed
4302                        + " animation=" + wtoken.mAppAnimator.animation
4303                        + " animating=" + wtoken.mAppAnimator.animating);
4304                DisplayContent displayContent = mTaskIdToDisplayContents.get(wtoken.groupId);
4305                if (delayed) {
4306                    // set the token aside because it has an active animation to be finished
4307                    if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
4308                            "removeAppToken make exiting: " + wtoken);
4309                    displayContent.mExitingAppTokens.add(wtoken);
4310                } else {
4311                    // Make sure there is no animation running on this token,
4312                    // so any windows associated with it will be removed as
4313                    // soon as their animations are complete
4314                    wtoken.mAppAnimator.clearAnimation();
4315                    wtoken.mAppAnimator.animating = false;
4316                }
4317                if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
4318                        "removeAppToken: " + wtoken);
4319                displayContent.removeAppToken(wtoken);
4320                wtoken.removed = true;
4321                if (wtoken.startingData != null) {
4322                    startingToken = wtoken;
4323                }
4324                unsetAppFreezingScreenLocked(wtoken, true, true);
4325                if (mFocusedApp == wtoken) {
4326                    if (DEBUG_FOCUS) Slog.v(TAG, "Removing focused app token:" + wtoken);
4327                    mFocusedApp = null;
4328                    updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
4329                    mInputMonitor.setFocusedAppLw(null);
4330                }
4331            } else {
4332                Slog.w(TAG, "Attempted to remove non-existing app token: " + token);
4333            }
4334
4335            if (!delayed && wtoken != null) {
4336                wtoken.updateReportedVisibilityLocked();
4337            }
4338        }
4339        Binder.restoreCallingIdentity(origId);
4340
4341        if (startingToken != null) {
4342            if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Schedule remove starting "
4343                    + startingToken + ": app token removed");
4344            Message m = mH.obtainMessage(H.REMOVE_STARTING, startingToken);
4345            mH.sendMessage(m);
4346        }
4347    }
4348
4349    private boolean tmpRemoveAppWindowsLocked(WindowToken token) {
4350        final int NW = token.windows.size();
4351        if (NW > 0) {
4352            mWindowsChanged = true;
4353        }
4354        for (int i=0; i<NW; i++) {
4355            WindowState win = token.windows.get(i);
4356            if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Tmp removing app window " + win);
4357            win.getWindowList().remove(win);
4358            int j = win.mChildWindows.size();
4359            while (j > 0) {
4360                j--;
4361                WindowState cwin = win.mChildWindows.get(j);
4362                if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
4363                        "Tmp removing child window " + cwin);
4364                cwin.getWindowList().remove(cwin);
4365            }
4366        }
4367        return NW > 0;
4368    }
4369
4370    void dumpAppTokensLocked() {
4371        DisplayContentsIterator iterator = new DisplayContentsIterator();
4372        while (iterator.hasNext()) {
4373            DisplayContent displayContent = iterator.next();
4374            Slog.v(TAG, "  Display " + displayContent.getDisplayId());
4375            AppTokenIterator appIterator = displayContent.getTmpAppIterator(REVERSE_ITERATOR);
4376            int i = appIterator.size();
4377            while (appIterator.hasNext()) {
4378                Slog.v(TAG, "  #" + --i + ": " + appIterator.next().token);
4379            }
4380        }
4381    }
4382
4383    void dumpWindowsLocked() {
4384        int i = 0;
4385        mTmpWindowsIterator.reset(REVERSE_ITERATOR);
4386        while (mTmpWindowsIterator.hasNext()) {
4387            final WindowState w = mTmpWindowsIterator.next();
4388            Slog.v(TAG, "  #" + i++ + ": " + w);
4389        }
4390    }
4391
4392    private int findAppWindowInsertionPointLocked(AppWindowToken target) {
4393        final int taskId = target.groupId;
4394        DisplayContent displayContent = mTaskIdToDisplayContents.get(taskId);
4395        if (displayContent == null) {
4396            Slog.w(TAG, "findTopAppWindowLocked: no DisplayContent for " + target);
4397            return 0;
4398        }
4399        final WindowList windows = displayContent.getWindowList();
4400        final int NW = windows.size();
4401
4402        AppTokenIterator iterator = displayContent.getTmpAppIterator(REVERSE_ITERATOR);
4403        while (iterator.hasNext()) {
4404            if (iterator.next() == target) {
4405                break;
4406            }
4407        }
4408
4409        while (iterator.hasNext()) {
4410            // Find the first app token below the new position that has
4411            // a window displayed.
4412            final AppWindowToken wtoken = iterator.next();
4413            if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows in " + wtoken.token);
4414            if (wtoken.sendingToBottom) {
4415                if (DEBUG_REORDER) Slog.v(TAG, "Skipping token -- currently sending to bottom");
4416                continue;
4417            }
4418            for (int i = wtoken.windows.size() - 1; i >= 0; --i) {
4419                WindowState win = wtoken.windows.get(i);
4420                for (int j = win.mChildWindows.size() - 1; j >= 0; --j) {
4421                    WindowState cwin = win.mChildWindows.get(j);
4422                    if (cwin.mSubLayer >= 0) {
4423                        for (int pos = NW - 1; pos >= 0; pos--) {
4424                            if (windows.get(pos) == cwin) {
4425                                if (DEBUG_REORDER) Slog.v(TAG,
4426                                        "Found child win @" + (pos + 1));
4427                                return pos + 1;
4428                            }
4429                        }
4430                    }
4431                }
4432                for (int pos = NW - 1; pos >= 0; pos--) {
4433                    if (windows.get(pos) == win) {
4434                        if (DEBUG_REORDER) Slog.v(TAG, "Found win @" + (pos + 1));
4435                        return pos + 1;
4436                    }
4437                }
4438            }
4439        }
4440
4441        return 0;
4442    }
4443
4444    private final int reAddWindowLocked(int index, WindowState win) {
4445        final WindowList windows = win.getWindowList();
4446        final int NCW = win.mChildWindows.size();
4447        boolean added = false;
4448        for (int j=0; j<NCW; j++) {
4449            WindowState cwin = win.mChildWindows.get(j);
4450            if (!added && cwin.mSubLayer >= 0) {
4451                if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding child window at "
4452                        + index + ": " + cwin);
4453                win.mRebuilding = false;
4454                windows.add(index, win);
4455                index++;
4456                added = true;
4457            }
4458            if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
4459                    + index + ": " + cwin);
4460            cwin.mRebuilding = false;
4461            windows.add(index, cwin);
4462            index++;
4463        }
4464        if (!added) {
4465            if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
4466                    + index + ": " + win);
4467            win.mRebuilding = false;
4468            windows.add(index, win);
4469            index++;
4470        }
4471        mWindowsChanged = true;
4472        return index;
4473    }
4474
4475    private final int reAddAppWindowsLocked(final DisplayContent displayContent, int index,
4476                                            WindowToken token) {
4477        final int NW = token.windows.size();
4478        for (int i=0; i<NW; i++) {
4479            final WindowState win = token.windows.get(i);
4480            if (win.mDisplayContent == displayContent) {
4481                index = reAddWindowLocked(index, win);
4482            }
4483        }
4484        return index;
4485    }
4486
4487    private void moveTaskWindowsLocked(int taskId) {
4488        DisplayContent displayContent = mTaskIdToDisplayContents.get(taskId);
4489        if (displayContent == null) {
4490            Slog.w(TAG, "moveTaskWindowsLocked: can't find DisplayContent for taskId=" + taskId);
4491            return;
4492        }
4493
4494        TaskList taskList = displayContent.mTaskIdToTaskList.get(taskId);
4495        if (taskList == null) {
4496            Slog.w(TAG, "moveTaskWindowsLocked: can't find TaskList for taskId=" + taskId);
4497            return;
4498        }
4499
4500        // First remove all of the windows from the list.
4501        for (AppWindowToken wtoken : taskList.mAppTokens) {
4502            tmpRemoveAppWindowsLocked(wtoken);
4503        }
4504
4505        // And now add them back at the correct place.
4506        // Where to start adding?
4507        int pos = findAppWindowInsertionPointLocked(taskList.mAppTokens.get(0));
4508        for (AppWindowToken wtoken : taskList.mAppTokens) {
4509            if (wtoken != null) {
4510                final int newPos = reAddAppWindowsLocked(displayContent, pos, wtoken);
4511                if (newPos != pos) {
4512                    displayContent.layoutNeeded = true;
4513                }
4514                pos = newPos;
4515            }
4516        }
4517        if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
4518            false /*updateInputWindows*/)) {
4519            assignLayersLocked(displayContent.getWindowList());
4520        }
4521
4522        updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
4523                false /*updateInputWindows*/);
4524        mInputMonitor.setUpdateInputWindowsNeededLw();
4525        performLayoutAndPlaceSurfacesLocked();
4526        mInputMonitor.updateInputWindowsLw(false /*force*/);
4527
4528        //dump();
4529    }
4530
4531    public void moveTaskToTop(int taskId) {
4532        final long origId = Binder.clearCallingIdentity();
4533        try {
4534            synchronized(mWindowMap) {
4535                DisplayContent displayContent = mTaskIdToDisplayContents.get(taskId);
4536                if (displayContent == null) {
4537                    Slog.e(TAG, "moveTaskToTop: taskId=" + taskId
4538                            + " not found in mTaskIdToDisplayContents");
4539                    return;
4540                }
4541                TaskList taskList = displayContent.mTaskIdToTaskList.get(taskId);
4542                if (taskList == null) {
4543                    Slog.e(TAG, "moveTaskToTop: taskId=" + taskId
4544                            + " not found in mTaskIdToTaskLists");
4545                    return;
4546                }
4547                if (!displayContent.mTaskLists.remove(taskList)) {
4548                    Slog.e(TAG, "moveTaskToTop: taskId=" + taskId + " not found in mTaskLists");
4549                }
4550                displayContent.mTaskLists.add(taskList);
4551
4552                moveTaskWindowsLocked(taskId);
4553            }
4554        } finally {
4555            Binder.restoreCallingIdentity(origId);
4556        }
4557    }
4558
4559    public void moveTaskToBottom(int taskId) {
4560        final long origId = Binder.clearCallingIdentity();
4561        try {
4562            synchronized(mWindowMap) {
4563                DisplayContent displayContent = mTaskIdToDisplayContents.get(taskId);
4564                if (displayContent == null) {
4565                    Slog.e(TAG, "moveTaskToBottom: taskId=" + taskId
4566                            + " not found in mTaskIdToDisplayContents");
4567                    return;
4568                }
4569                TaskList taskList = displayContent.mTaskIdToTaskList.get(taskId);
4570                if (taskList == null) {
4571                    Slog.e(TAG, "moveTaskToTopBottom: taskId=" + taskId
4572                            + " not found in mTaskIdToTaskLists");
4573                    return;
4574                }
4575                if (!displayContent.mTaskLists.remove(taskList)) {
4576                    Slog.e(TAG, "moveTaskToBottom: taskId=" + taskId + " not found in mTaskLists");
4577                }
4578                displayContent.mTaskLists.add(0, taskList);
4579
4580                moveTaskWindowsLocked(taskId);
4581            }
4582        } finally {
4583            Binder.restoreCallingIdentity(origId);
4584        }
4585    }
4586
4587    // -------------------------------------------------------------
4588    // Misc IWindowSession methods
4589    // -------------------------------------------------------------
4590
4591    @Override
4592    public void startFreezingScreen(int exitAnim, int enterAnim) {
4593        if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
4594                "startFreezingScreen()")) {
4595            throw new SecurityException("Requires FREEZE_SCREEN permission");
4596        }
4597
4598        synchronized(mWindowMap) {
4599            if (!mClientFreezingScreen) {
4600                mClientFreezingScreen = true;
4601                final long origId = Binder.clearCallingIdentity();
4602                try {
4603                    startFreezingDisplayLocked(false, exitAnim, enterAnim);
4604                    mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
4605                    mH.sendEmptyMessageDelayed(H.CLIENT_FREEZE_TIMEOUT, 5000);
4606                } finally {
4607                    Binder.restoreCallingIdentity(origId);
4608                }
4609            }
4610        }
4611    }
4612
4613    @Override
4614    public void stopFreezingScreen() {
4615        if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
4616                "stopFreezingScreen()")) {
4617            throw new SecurityException("Requires FREEZE_SCREEN permission");
4618        }
4619
4620        synchronized(mWindowMap) {
4621            if (mClientFreezingScreen) {
4622                mClientFreezingScreen = false;
4623                final long origId = Binder.clearCallingIdentity();
4624                try {
4625                    stopFreezingDisplayLocked();
4626                } finally {
4627                    Binder.restoreCallingIdentity(origId);
4628                }
4629            }
4630        }
4631    }
4632
4633    @Override
4634    public void disableKeyguard(IBinder token, String tag) {
4635        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
4636            != PackageManager.PERMISSION_GRANTED) {
4637            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
4638        }
4639
4640        mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
4641                KeyguardDisableHandler.KEYGUARD_DISABLE, new Pair<IBinder, String>(token, tag)));
4642    }
4643
4644    @Override
4645    public void reenableKeyguard(IBinder token) {
4646        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
4647            != PackageManager.PERMISSION_GRANTED) {
4648            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
4649        }
4650
4651        mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
4652                KeyguardDisableHandler.KEYGUARD_REENABLE, token));
4653    }
4654
4655    /**
4656     * @see android.app.KeyguardManager#exitKeyguardSecurely
4657     */
4658    @Override
4659    public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) {
4660        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
4661            != PackageManager.PERMISSION_GRANTED) {
4662            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
4663        }
4664        mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() {
4665            @Override
4666            public void onKeyguardExitResult(boolean success) {
4667                try {
4668                    callback.onKeyguardExitResult(success);
4669                } catch (RemoteException e) {
4670                    // Client has died, we don't care.
4671                }
4672            }
4673        });
4674    }
4675
4676    @Override
4677    public boolean inKeyguardRestrictedInputMode() {
4678        return mPolicy.inKeyguardRestrictedKeyInputMode();
4679    }
4680
4681    @Override
4682    public boolean isKeyguardLocked() {
4683        return mPolicy.isKeyguardLocked();
4684    }
4685
4686    @Override
4687    public boolean isKeyguardSecure() {
4688        return mPolicy.isKeyguardSecure();
4689    }
4690
4691    @Override
4692    public void dismissKeyguard() {
4693        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
4694                != PackageManager.PERMISSION_GRANTED) {
4695            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
4696        }
4697        synchronized(mWindowMap) {
4698            mPolicy.dismissKeyguardLw();
4699        }
4700    }
4701
4702    @Override
4703    public void closeSystemDialogs(String reason) {
4704        synchronized(mWindowMap) {
4705            mTmpWindowsIterator.reset(FORWARD_ITERATOR);
4706            while (mTmpWindowsIterator.hasNext()) {
4707                final WindowState w = mTmpWindowsIterator.next();
4708                if (w.mHasSurface) {
4709                    try {
4710                        w.mClient.closeSystemDialogs(reason);
4711                    } catch (RemoteException e) {
4712                    }
4713                }
4714            }
4715        }
4716    }
4717
4718    static float fixScale(float scale) {
4719        if (scale < 0) scale = 0;
4720        else if (scale > 20) scale = 20;
4721        return Math.abs(scale);
4722    }
4723
4724    @Override
4725    public void setAnimationScale(int which, float scale) {
4726        if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
4727                "setAnimationScale()")) {
4728            throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
4729        }
4730
4731        if (scale < 0) scale = 0;
4732        else if (scale > 20) scale = 20;
4733        scale = Math.abs(scale);
4734        switch (which) {
4735            case 0: mWindowAnimationScale = fixScale(scale); break;
4736            case 1: mTransitionAnimationScale = fixScale(scale); break;
4737            case 2: mAnimatorDurationScale = fixScale(scale); break;
4738        }
4739
4740        // Persist setting
4741        mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
4742    }
4743
4744    @Override
4745    public void setAnimationScales(float[] scales) {
4746        if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
4747                "setAnimationScale()")) {
4748            throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
4749        }
4750
4751        if (scales != null) {
4752            if (scales.length >= 1) {
4753                mWindowAnimationScale = fixScale(scales[0]);
4754            }
4755            if (scales.length >= 2) {
4756                mTransitionAnimationScale = fixScale(scales[1]);
4757            }
4758            if (scales.length >= 3) {
4759                setAnimatorDurationScale(fixScale(scales[2]));
4760            }
4761        }
4762
4763        // Persist setting
4764        mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
4765    }
4766
4767    private void setAnimatorDurationScale(float scale) {
4768        mAnimatorDurationScale = scale;
4769        ValueAnimator.setDurationScale(scale);
4770    }
4771
4772    @Override
4773    public float getAnimationScale(int which) {
4774        switch (which) {
4775            case 0: return mWindowAnimationScale;
4776            case 1: return mTransitionAnimationScale;
4777            case 2: return mAnimatorDurationScale;
4778        }
4779        return 0;
4780    }
4781
4782    @Override
4783    public float[] getAnimationScales() {
4784        return new float[] { mWindowAnimationScale, mTransitionAnimationScale,
4785                mAnimatorDurationScale };
4786    }
4787
4788    // Called by window manager policy. Not exposed externally.
4789    @Override
4790    public int getLidState() {
4791        int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY,
4792                InputManagerService.SW_LID);
4793        if (sw > 0) {
4794            // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL.
4795            return LID_CLOSED;
4796        } else if (sw == 0) {
4797            // Switch state: AKEY_STATE_UP.
4798            return LID_OPEN;
4799        } else {
4800            // Switch state: AKEY_STATE_UNKNOWN.
4801            return LID_ABSENT;
4802        }
4803    }
4804
4805    // Called by window manager policy.  Not exposed externally.
4806    @Override
4807    public InputChannel monitorInput(String inputChannelName) {
4808        return mInputManager.monitorInput(inputChannelName);
4809    }
4810
4811    // Called by window manager policy.  Not exposed externally.
4812    @Override
4813    public void switchKeyboardLayout(int deviceId, int direction) {
4814        mInputManager.switchKeyboardLayout(deviceId, direction);
4815    }
4816
4817    // Called by window manager policy.  Not exposed externally.
4818    @Override
4819    public void shutdown(boolean confirm) {
4820        ShutdownThread.shutdown(mContext, confirm);
4821    }
4822
4823    // Called by window manager policy.  Not exposed externally.
4824    @Override
4825    public void rebootSafeMode(boolean confirm) {
4826        ShutdownThread.rebootSafeMode(mContext, confirm);
4827    }
4828
4829    @Override
4830    public void setInputFilter(IInputFilter filter) {
4831        if (!checkCallingPermission(android.Manifest.permission.FILTER_EVENTS, "setInputFilter()")) {
4832            throw new SecurityException("Requires FILTER_EVENTS permission");
4833        }
4834        mInputManager.setInputFilter(filter);
4835    }
4836
4837    public void setCurrentUser(final int newUserId) {
4838        synchronized (mWindowMap) {
4839            mCurrentUserId = newUserId;
4840            mPolicy.setCurrentUserLw(newUserId);
4841
4842            // Hide windows that should not be seen by the new user.
4843            DisplayContentsIterator iterator = new DisplayContentsIterator();
4844            while (iterator.hasNext()) {
4845                final WindowList windows = iterator.next().getWindowList();
4846                for (int i = 0; i < windows.size(); i++) {
4847                    final WindowState win = windows.get(i);
4848                    if (win.isHiddenFromUserLocked()) {
4849                        Slog.w(TAG, "current user violation " + newUserId + " hiding "
4850                                + win + ", attrs=" + win.mAttrs.type + ", belonging to "
4851                                + win.mOwnerUid);
4852                        win.hideLw(false);
4853                    }
4854                }
4855            }
4856            performLayoutAndPlaceSurfacesLocked();
4857        }
4858    }
4859
4860    public void enableScreenAfterBoot() {
4861        synchronized(mWindowMap) {
4862            if (DEBUG_BOOT) {
4863                RuntimeException here = new RuntimeException("here");
4864                here.fillInStackTrace();
4865                Slog.i(TAG, "enableScreenAfterBoot: mDisplayEnabled=" + mDisplayEnabled
4866                        + " mForceDisplayEnabled=" + mForceDisplayEnabled
4867                        + " mShowingBootMessages=" + mShowingBootMessages
4868                        + " mSystemBooted=" + mSystemBooted, here);
4869            }
4870            if (mSystemBooted) {
4871                return;
4872            }
4873            mSystemBooted = true;
4874            hideBootMessagesLocked();
4875            // If the screen still doesn't come up after 30 seconds, give
4876            // up and turn it on.
4877            mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30*1000);
4878        }
4879
4880        mPolicy.systemBooted();
4881
4882        performEnableScreen();
4883    }
4884
4885    void enableScreenIfNeededLocked() {
4886        if (DEBUG_BOOT) {
4887            RuntimeException here = new RuntimeException("here");
4888            here.fillInStackTrace();
4889            Slog.i(TAG, "enableScreenIfNeededLocked: mDisplayEnabled=" + mDisplayEnabled
4890                    + " mForceDisplayEnabled=" + mForceDisplayEnabled
4891                    + " mShowingBootMessages=" + mShowingBootMessages
4892                    + " mSystemBooted=" + mSystemBooted, here);
4893        }
4894        if (mDisplayEnabled) {
4895            return;
4896        }
4897        if (!mSystemBooted && !mShowingBootMessages) {
4898            return;
4899        }
4900        mH.sendEmptyMessage(H.ENABLE_SCREEN);
4901    }
4902
4903    public void performBootTimeout() {
4904        synchronized(mWindowMap) {
4905            if (mDisplayEnabled || mHeadless) {
4906                return;
4907            }
4908            Slog.w(TAG, "***** BOOT TIMEOUT: forcing display enabled");
4909            mForceDisplayEnabled = true;
4910        }
4911        performEnableScreen();
4912    }
4913
4914    public void performEnableScreen() {
4915        synchronized(mWindowMap) {
4916            if (DEBUG_BOOT) {
4917                RuntimeException here = new RuntimeException("here");
4918                here.fillInStackTrace();
4919                Slog.i(TAG, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled
4920                        + " mForceDisplayEnabled=" + mForceDisplayEnabled
4921                        + " mShowingBootMessages=" + mShowingBootMessages
4922                        + " mSystemBooted=" + mSystemBooted
4923                        + " mOnlyCore=" + mOnlyCore, here);
4924            }
4925            if (mDisplayEnabled) {
4926                return;
4927            }
4928            if (!mSystemBooted && !mShowingBootMessages) {
4929                return;
4930            }
4931
4932            if (!mForceDisplayEnabled) {
4933                // Don't enable the screen until all existing windows
4934                // have been drawn.
4935                boolean haveBootMsg = false;
4936                boolean haveApp = false;
4937                // if the wallpaper service is disabled on the device, we're never going to have
4938                // wallpaper, don't bother waiting for it
4939                boolean haveWallpaper = false;
4940                boolean wallpaperEnabled = mContext.getResources().getBoolean(
4941                        com.android.internal.R.bool.config_enableWallpaperService)
4942                        && !mOnlyCore;
4943                boolean haveKeyguard = true;
4944                // TODO(multidisplay): Expand to all displays?
4945                final WindowList windows = getDefaultWindowListLocked();
4946                final int N = windows.size();
4947                for (int i=0; i<N; i++) {
4948                    WindowState w = windows.get(i);
4949                    if (w.mAttrs.type == TYPE_KEYGUARD) {
4950                        // Only if there is a keyguard attached to the window manager
4951                        // will we consider ourselves as having a keyguard.  If it
4952                        // isn't attached, we don't know if it wants to be shown or
4953                        // hidden.  If it is attached, we will say we have a keyguard
4954                        // if the window doesn't want to be visible, because in that
4955                        // case it explicitly doesn't want to be shown so we should
4956                        // not delay turning the screen on for it.
4957                        boolean vis = w.mViewVisibility == View.VISIBLE
4958                                && w.mPolicyVisibility;
4959                        haveKeyguard = !vis;
4960                    }
4961                    if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
4962                        return;
4963                    }
4964                    if (w.isDrawnLw()) {
4965                        if (w.mAttrs.type == TYPE_BOOT_PROGRESS) {
4966                            haveBootMsg = true;
4967                        } else if (w.mAttrs.type == TYPE_APPLICATION) {
4968                            haveApp = true;
4969                        } else if (w.mAttrs.type == TYPE_WALLPAPER) {
4970                            haveWallpaper = true;
4971                        } else if (w.mAttrs.type == TYPE_KEYGUARD) {
4972                            haveKeyguard = true;
4973                        }
4974                    }
4975                }
4976
4977                if (DEBUG_SCREEN_ON || DEBUG_BOOT) {
4978                    Slog.i(TAG, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages
4979                            + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp
4980                            + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled
4981                            + " haveKeyguard=" + haveKeyguard);
4982                }
4983
4984                // If we are turning on the screen to show the boot message,
4985                // don't do it until the boot message is actually displayed.
4986                if (!mSystemBooted && !haveBootMsg) {
4987                    return;
4988                }
4989
4990                // If we are turning on the screen after the boot is completed
4991                // normally, don't do so until we have the application and
4992                // wallpaper.
4993                if (mSystemBooted && ((!haveApp && !haveKeyguard) ||
4994                        (wallpaperEnabled && !haveWallpaper))) {
4995                    return;
4996                }
4997            }
4998
4999            mDisplayEnabled = true;
5000            if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG, "******************** ENABLING SCREEN!");
5001            if (false) {
5002                StringWriter sw = new StringWriter();
5003                PrintWriter pw = new PrintWriter(sw);
5004                this.dump(null, pw, null);
5005                Slog.i(TAG, sw.toString());
5006            }
5007            try {
5008                IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
5009                if (surfaceFlinger != null) {
5010                    //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
5011                    Parcel data = Parcel.obtain();
5012                    data.writeInterfaceToken("android.ui.ISurfaceComposer");
5013                    surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
5014                                            data, null, 0);
5015                    data.recycle();
5016                }
5017            } catch (RemoteException ex) {
5018                Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!");
5019            }
5020
5021            // Enable input dispatch.
5022            mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled);
5023        }
5024
5025        mPolicy.enableScreenAfterBoot();
5026
5027        // Make sure the last requested orientation has been applied.
5028        updateRotationUnchecked(false, false);
5029    }
5030
5031    public void showBootMessage(final CharSequence msg, final boolean always) {
5032        boolean first = false;
5033        synchronized(mWindowMap) {
5034            if (DEBUG_BOOT) {
5035                RuntimeException here = new RuntimeException("here");
5036                here.fillInStackTrace();
5037                Slog.i(TAG, "showBootMessage: msg=" + msg + " always=" + always
5038                        + " mAllowBootMessages=" + mAllowBootMessages
5039                        + " mShowingBootMessages=" + mShowingBootMessages
5040                        + " mSystemBooted=" + mSystemBooted, here);
5041            }
5042            if (!mAllowBootMessages) {
5043                return;
5044            }
5045            if (!mShowingBootMessages) {
5046                if (!always) {
5047                    return;
5048                }
5049                first = true;
5050            }
5051            if (mSystemBooted) {
5052                return;
5053            }
5054            mShowingBootMessages = true;
5055            mPolicy.showBootMessage(msg, always);
5056        }
5057        if (first) {
5058            performEnableScreen();
5059        }
5060    }
5061
5062    public void hideBootMessagesLocked() {
5063        if (DEBUG_BOOT) {
5064            RuntimeException here = new RuntimeException("here");
5065            here.fillInStackTrace();
5066            Slog.i(TAG, "hideBootMessagesLocked: mDisplayEnabled=" + mDisplayEnabled
5067                    + " mForceDisplayEnabled=" + mForceDisplayEnabled
5068                    + " mShowingBootMessages=" + mShowingBootMessages
5069                    + " mSystemBooted=" + mSystemBooted, here);
5070        }
5071        if (mShowingBootMessages) {
5072            mShowingBootMessages = false;
5073            mPolicy.hideBootMessages();
5074        }
5075    }
5076
5077    @Override
5078    public void setInTouchMode(boolean mode) {
5079        synchronized(mWindowMap) {
5080            mInTouchMode = mode;
5081        }
5082    }
5083
5084    // TODO: more accounting of which pid(s) turned it on, keep count,
5085    // only allow disables from pids which have count on, etc.
5086    @Override
5087    public void showStrictModeViolation(boolean on) {
5088        if (mHeadless) return;
5089        int pid = Binder.getCallingPid();
5090        mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, pid));
5091    }
5092
5093    private void showStrictModeViolation(int arg, int pid) {
5094        final boolean on = arg != 0;
5095        synchronized(mWindowMap) {
5096            // Ignoring requests to enable the red border from clients
5097            // which aren't on screen.  (e.g. Broadcast Receivers in
5098            // the background..)
5099            if (on) {
5100                boolean isVisible = false;
5101                mTmpWindowsIterator.reset(FORWARD_ITERATOR);
5102                while (mTmpWindowsIterator.hasNext()) {
5103                    final WindowState ws = mTmpWindowsIterator.next();
5104                    if (ws.mSession.mPid == pid && ws.isVisibleLw()) {
5105                        isVisible = true;
5106                        break;
5107                    }
5108                }
5109                if (!isVisible) {
5110                    return;
5111                }
5112            }
5113
5114            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5115                    ">>> OPEN TRANSACTION showStrictModeViolation");
5116            SurfaceControl.openTransaction();
5117            try {
5118                // TODO(multi-display): support multiple displays
5119                if (mStrictModeFlash == null) {
5120                    mStrictModeFlash = new StrictModeFlash(
5121                            getDefaultDisplayContentLocked().getDisplay(), mFxSession);
5122                }
5123                mStrictModeFlash.setVisibility(on);
5124            } finally {
5125                SurfaceControl.closeTransaction();
5126                if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5127                        "<<< CLOSE TRANSACTION showStrictModeViolation");
5128            }
5129        }
5130    }
5131
5132    @Override
5133    public void setStrictModeVisualIndicatorPreference(String value) {
5134        SystemProperties.set(StrictMode.VISUAL_PROPERTY, value);
5135    }
5136
5137    /**
5138     * Takes a snapshot of the screen.  In landscape mode this grabs the whole screen.
5139     * In portrait mode, it grabs the upper region of the screen based on the vertical dimension
5140     * of the target image.
5141     *
5142     * @param displayId the Display to take a screenshot of.
5143     * @param width the width of the target bitmap
5144     * @param height the height of the target bitmap
5145     */
5146    @Override
5147    public Bitmap screenshotApplications(IBinder appToken, int displayId, int width, int height) {
5148        if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
5149                "screenshotApplications()")) {
5150            throw new SecurityException("Requires READ_FRAME_BUFFER permission");
5151        }
5152
5153        Bitmap rawss;
5154
5155        int maxLayer = 0;
5156        final Rect frame = new Rect();
5157
5158        float scale;
5159        int dw, dh;
5160        int rot;
5161
5162        synchronized(mWindowMap) {
5163            long ident = Binder.clearCallingIdentity();
5164
5165            final DisplayContent displayContent = getDisplayContentLocked(displayId);
5166            if (displayContent == null) {
5167                return null;
5168            }
5169            final DisplayInfo displayInfo = displayContent.getDisplayInfo();
5170            dw = displayInfo.logicalWidth;
5171            dh = displayInfo.logicalHeight;
5172
5173            int aboveAppLayer = mPolicy.windowTypeToLayerLw(TYPE_APPLICATION)
5174                    * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
5175            aboveAppLayer += TYPE_LAYER_MULTIPLIER;
5176
5177            boolean isImeTarget = mInputMethodTarget != null
5178                    && mInputMethodTarget.mAppToken != null
5179                    && mInputMethodTarget.mAppToken.appToken != null
5180                    && mInputMethodTarget.mAppToken.appToken.asBinder() == appToken;
5181
5182            // Figure out the part of the screen that is actually the app.
5183            boolean including = false;
5184            final WindowList windows = displayContent.getWindowList();
5185            for (int i = windows.size() - 1; i >= 0; i--) {
5186                WindowState ws = windows.get(i);
5187                if (!ws.mHasSurface) {
5188                    continue;
5189                }
5190                if (ws.mLayer >= aboveAppLayer) {
5191                    continue;
5192                }
5193                // When we will skip windows: when we are not including
5194                // ones behind a window we didn't skip, and we are actually
5195                // taking a screenshot of a specific app.
5196                if (!including && appToken != null) {
5197                    // Also, we can possibly skip this window if it is not
5198                    // an IME target or the application for the screenshot
5199                    // is not the current IME target.
5200                    if (!ws.mIsImWindow || !isImeTarget) {
5201                        // And finally, this window is of no interest if it
5202                        // is not associated with the screenshot app.
5203                        if (ws.mAppToken == null || ws.mAppToken.token != appToken) {
5204                            continue;
5205                        }
5206                    }
5207                }
5208
5209                // We keep on including windows until we go past a full-screen
5210                // window.
5211                including = !ws.mIsImWindow && !ws.isFullscreen(dw, dh);
5212
5213                if (maxLayer < ws.mWinAnimator.mSurfaceLayer) {
5214                    maxLayer = ws.mWinAnimator.mSurfaceLayer;
5215                }
5216
5217                // Don't include wallpaper in bounds calculation
5218                if (!ws.mIsWallpaper) {
5219                    final Rect wf = ws.mFrame;
5220                    final Rect cr = ws.mContentInsets;
5221                    int left = wf.left + cr.left;
5222                    int top = wf.top + cr.top;
5223                    int right = wf.right - cr.right;
5224                    int bottom = wf.bottom - cr.bottom;
5225                    frame.union(left, top, right, bottom);
5226                }
5227            }
5228            Binder.restoreCallingIdentity(ident);
5229
5230            // Constrain frame to the screen size.
5231            frame.intersect(0, 0, dw, dh);
5232
5233            if (frame.isEmpty() || maxLayer == 0) {
5234                return null;
5235            }
5236
5237            // The screenshot API does not apply the current screen rotation.
5238            rot = getDefaultDisplayContentLocked().getDisplay().getRotation();
5239            int fw = frame.width();
5240            int fh = frame.height();
5241
5242            // Constrain thumbnail to smaller of screen width or height. Assumes aspect
5243            // of thumbnail is the same as the screen (in landscape) or square.
5244            float targetWidthScale = width / (float) fw;
5245            float targetHeightScale = height / (float) fh;
5246            if (dw <= dh) {
5247                scale = targetWidthScale;
5248                // If aspect of thumbnail is the same as the screen (in landscape),
5249                // select the slightly larger value so we fill the entire bitmap
5250                if (targetHeightScale > scale && (int) (targetHeightScale * fw) == width) {
5251                    scale = targetHeightScale;
5252                }
5253            } else {
5254                scale = targetHeightScale;
5255                // If aspect of thumbnail is the same as the screen (in landscape),
5256                // select the slightly larger value so we fill the entire bitmap
5257                if (targetWidthScale > scale && (int) (targetWidthScale * fh) == height) {
5258                    scale = targetWidthScale;
5259                }
5260            }
5261
5262            // The screen shot will contain the entire screen.
5263            dw = (int)(dw*scale);
5264            dh = (int)(dh*scale);
5265            if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
5266                int tmp = dw;
5267                dw = dh;
5268                dh = tmp;
5269                rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90;
5270            }
5271            if (DEBUG_SCREENSHOT) {
5272                Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from 0 to " + maxLayer);
5273                for (int i = 0; i < windows.size(); i++) {
5274                    WindowState win = windows.get(i);
5275                    Slog.i(TAG, win + ": " + win.mLayer
5276                            + " animLayer=" + win.mWinAnimator.mAnimLayer
5277                            + " surfaceLayer=" + win.mWinAnimator.mSurfaceLayer);
5278                }
5279            }
5280            rawss = SurfaceControl.screenshot(dw, dh, 0, maxLayer);
5281        }
5282
5283        if (rawss == null) {
5284            Slog.w(TAG, "Failure taking screenshot for (" + dw + "x" + dh
5285                    + ") to layer " + maxLayer);
5286            return null;
5287        }
5288
5289        Bitmap bm = Bitmap.createBitmap(width, height, rawss.getConfig());
5290        Matrix matrix = new Matrix();
5291        ScreenRotationAnimation.createRotationMatrix(rot, dw, dh, matrix);
5292        matrix.postTranslate(-FloatMath.ceil(frame.left*scale), -FloatMath.ceil(frame.top*scale));
5293        Canvas canvas = new Canvas(bm);
5294        canvas.drawBitmap(rawss, matrix, null);
5295        canvas.setBitmap(null);
5296
5297        rawss.recycle();
5298        return bm;
5299    }
5300
5301    /**
5302     * Freeze rotation changes.  (Enable "rotation lock".)
5303     * Persists across reboots.
5304     * @param rotation The desired rotation to freeze to, or -1 to use the
5305     * current rotation.
5306     */
5307    @Override
5308    public void freezeRotation(int rotation) {
5309        if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
5310                "freezeRotation()")) {
5311            throw new SecurityException("Requires SET_ORIENTATION permission");
5312        }
5313        if (rotation < -1 || rotation > Surface.ROTATION_270) {
5314            throw new IllegalArgumentException("Rotation argument must be -1 or a valid "
5315                    + "rotation constant.");
5316        }
5317
5318        if (DEBUG_ORIENTATION) Slog.v(TAG, "freezeRotation: mRotation=" + mRotation);
5319
5320        long origId = Binder.clearCallingIdentity();
5321        try {
5322            mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED,
5323                    rotation == -1 ? mRotation : rotation);
5324        } finally {
5325            Binder.restoreCallingIdentity(origId);
5326        }
5327
5328        updateRotationUnchecked(false, false);
5329    }
5330
5331    /**
5332     * Thaw rotation changes.  (Disable "rotation lock".)
5333     * Persists across reboots.
5334     */
5335    @Override
5336    public void thawRotation() {
5337        if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
5338                "thawRotation()")) {
5339            throw new SecurityException("Requires SET_ORIENTATION permission");
5340        }
5341
5342        if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation);
5343
5344        long origId = Binder.clearCallingIdentity();
5345        try {
5346            mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE,
5347                    777); // rot not used
5348        } finally {
5349            Binder.restoreCallingIdentity(origId);
5350        }
5351
5352        updateRotationUnchecked(false, false);
5353    }
5354
5355    /**
5356     * Recalculate the current rotation.
5357     *
5358     * Called by the window manager policy whenever the state of the system changes
5359     * such that the current rotation might need to be updated, such as when the
5360     * device is docked or rotated into a new posture.
5361     */
5362    @Override
5363    public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
5364        updateRotationUnchecked(alwaysSendConfiguration, forceRelayout);
5365    }
5366
5367    /**
5368     * Temporarily pauses rotation changes until resumed.
5369     *
5370     * This can be used to prevent rotation changes from occurring while the user is
5371     * performing certain operations, such as drag and drop.
5372     *
5373     * This call nests and must be matched by an equal number of calls to
5374     * {@link #resumeRotationLocked}.
5375     */
5376    void pauseRotationLocked() {
5377        mDeferredRotationPauseCount += 1;
5378    }
5379
5380    /**
5381     * Resumes normal rotation changes after being paused.
5382     */
5383    void resumeRotationLocked() {
5384        if (mDeferredRotationPauseCount > 0) {
5385            mDeferredRotationPauseCount -= 1;
5386            if (mDeferredRotationPauseCount == 0) {
5387                boolean changed = updateRotationUncheckedLocked(false);
5388                if (changed) {
5389                    mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
5390                }
5391            }
5392        }
5393    }
5394
5395    public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) {
5396        if(DEBUG_ORIENTATION) Slog.v(TAG, "updateRotationUnchecked("
5397                   + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")");
5398
5399        long origId = Binder.clearCallingIdentity();
5400        boolean changed;
5401        synchronized(mWindowMap) {
5402            changed = updateRotationUncheckedLocked(false);
5403            if (!changed || forceRelayout) {
5404                getDefaultDisplayContentLocked().layoutNeeded = true;
5405                performLayoutAndPlaceSurfacesLocked();
5406            }
5407        }
5408
5409        if (changed || alwaysSendConfiguration) {
5410            sendNewConfiguration();
5411        }
5412
5413        Binder.restoreCallingIdentity(origId);
5414    }
5415
5416    // TODO(multidisplay): Rotate any display?
5417    /**
5418     * Updates the current rotation.
5419     *
5420     * Returns true if the rotation has been changed.  In this case YOU
5421     * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN.
5422     */
5423    public boolean updateRotationUncheckedLocked(boolean inTransaction) {
5424        if (mDeferredRotationPauseCount > 0) {
5425            // Rotation updates have been paused temporarily.  Defer the update until
5426            // updates have been resumed.
5427            if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, rotation is paused.");
5428            return false;
5429        }
5430
5431        ScreenRotationAnimation screenRotationAnimation =
5432                mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
5433        if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
5434            // Rotation updates cannot be performed while the previous rotation change
5435            // animation is still in progress.  Skip this update.  We will try updating
5436            // again after the animation is finished and the display is unfrozen.
5437            if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, animation in progress.");
5438            return false;
5439        }
5440
5441        if (!mDisplayEnabled) {
5442            // No point choosing a rotation if the display is not enabled.
5443            if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, display is not enabled.");
5444            return false;
5445        }
5446
5447        // TODO: Implement forced rotation changes.
5448        //       Set mAltOrientation to indicate that the application is receiving
5449        //       an orientation that has different metrics than it expected.
5450        //       eg. Portrait instead of Landscape.
5451
5452        int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation);
5453        boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw(
5454                mForcedAppOrientation, rotation);
5455
5456        if (DEBUG_ORIENTATION) {
5457            Slog.v(TAG, "Application requested orientation "
5458                    + mForcedAppOrientation + ", got rotation " + rotation
5459                    + " which has " + (altOrientation ? "incompatible" : "compatible")
5460                    + " metrics");
5461        }
5462
5463        if (mRotation == rotation && mAltOrientation == altOrientation) {
5464            // No change.
5465            return false;
5466        }
5467
5468        if (DEBUG_ORIENTATION) {
5469            Slog.v(TAG,
5470                "Rotation changed to " + rotation + (altOrientation ? " (alt)" : "")
5471                + " from " + mRotation + (mAltOrientation ? " (alt)" : "")
5472                + ", forceApp=" + mForcedAppOrientation);
5473        }
5474
5475        mRotation = rotation;
5476        mAltOrientation = altOrientation;
5477        mPolicy.setRotationLw(mRotation);
5478
5479        mWindowsFreezingScreen = true;
5480        mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
5481        mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION);
5482        mWaitingForConfig = true;
5483        getDefaultDisplayContentLocked().layoutNeeded = true;
5484        startFreezingDisplayLocked(inTransaction, 0, 0);
5485        // startFreezingDisplayLocked can reset the ScreenRotationAnimation.
5486        screenRotationAnimation =
5487                mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
5488
5489        // We need to update our screen size information to match the new
5490        // rotation.  Note that this is redundant with the later call to
5491        // sendNewConfiguration() that must be called after this function
5492        // returns...  however we need to do the screen size part of that
5493        // before then so we have the correct size to use when initializing
5494        // the rotation animation for the new rotation.
5495        computeScreenConfigurationLocked(null);
5496
5497        final DisplayContent displayContent = getDefaultDisplayContentLocked();
5498        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
5499        if (!inTransaction) {
5500            if (SHOW_TRANSACTIONS) {
5501                Slog.i(TAG, ">>> OPEN TRANSACTION setRotationUnchecked");
5502            }
5503            SurfaceControl.openTransaction();
5504        }
5505        try {
5506            // NOTE: We disable the rotation in the emulator because
5507            //       it doesn't support hardware OpenGL emulation yet.
5508            if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
5509                    && screenRotationAnimation.hasScreenshot()) {
5510                if (screenRotationAnimation.setRotationInTransaction(
5511                        rotation, mFxSession,
5512                        MAX_ANIMATION_DURATION, mTransitionAnimationScale,
5513                        displayInfo.logicalWidth, displayInfo.logicalHeight)) {
5514                    scheduleAnimationLocked();
5515                }
5516            }
5517
5518            mDisplayManagerService.performTraversalInTransactionFromWindowManager();
5519        } finally {
5520            if (!inTransaction) {
5521                SurfaceControl.closeTransaction();
5522                if (SHOW_LIGHT_TRANSACTIONS) {
5523                    Slog.i(TAG, "<<< CLOSE TRANSACTION setRotationUnchecked");
5524                }
5525            }
5526        }
5527
5528        final WindowList windows = displayContent.getWindowList();
5529        for (int i = windows.size() - 1; i >= 0; i--) {
5530            WindowState w = windows.get(i);
5531            if (w.mHasSurface) {
5532                if (DEBUG_ORIENTATION) Slog.v(TAG, "Set mOrientationChanging of " + w);
5533                w.mOrientationChanging = true;
5534                mInnerFields.mOrientationChangeComplete = false;
5535            }
5536        }
5537
5538        for (int i=mRotationWatchers.size()-1; i>=0; i--) {
5539            try {
5540                mRotationWatchers.get(i).onRotationChanged(rotation);
5541            } catch (RemoteException e) {
5542            }
5543        }
5544
5545        //TODO (multidisplay): Magnification is supported only for the default display.
5546        if (mDisplayMagnifier != null
5547                && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) {
5548            mDisplayMagnifier.onRotationChangedLocked(getDefaultDisplayContentLocked(), rotation);
5549        }
5550
5551        return true;
5552    }
5553
5554    @Override
5555    public int getRotation() {
5556        return mRotation;
5557    }
5558
5559    @Override
5560    public boolean isRotationFrozen() {
5561        return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED;
5562    }
5563
5564    @Override
5565    public int watchRotation(IRotationWatcher watcher) {
5566        final IBinder watcherBinder = watcher.asBinder();
5567        IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
5568            @Override
5569            public void binderDied() {
5570                synchronized (mWindowMap) {
5571                    for (int i=0; i<mRotationWatchers.size(); i++) {
5572                        if (watcherBinder == mRotationWatchers.get(i).asBinder()) {
5573                            IRotationWatcher removed = mRotationWatchers.remove(i);
5574                            if (removed != null) {
5575                                removed.asBinder().unlinkToDeath(this, 0);
5576                            }
5577                            i--;
5578                        }
5579                    }
5580                }
5581            }
5582        };
5583
5584        synchronized (mWindowMap) {
5585            try {
5586                watcher.asBinder().linkToDeath(dr, 0);
5587                mRotationWatchers.add(watcher);
5588            } catch (RemoteException e) {
5589                // Client died, no cleanup needed.
5590            }
5591
5592            return mRotation;
5593        }
5594    }
5595
5596    /**
5597     * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact
5598     * theme attribute) on devices that feature a physical options menu key attempt to position
5599     * their menu panel window along the edge of the screen nearest the physical menu key.
5600     * This lowers the travel distance between invoking the menu panel and selecting
5601     * a menu option.
5602     *
5603     * This method helps control where that menu is placed. Its current implementation makes
5604     * assumptions about the menu key and its relationship to the screen based on whether
5605     * the device's natural orientation is portrait (width < height) or landscape.
5606     *
5607     * The menu key is assumed to be located along the bottom edge of natural-portrait
5608     * devices and along the right edge of natural-landscape devices. If these assumptions
5609     * do not hold for the target device, this method should be changed to reflect that.
5610     *
5611     * @return A {@link Gravity} value for placing the options menu window
5612     */
5613    @Override
5614    public int getPreferredOptionsPanelGravity() {
5615        synchronized (mWindowMap) {
5616            final int rotation = getRotation();
5617
5618            // TODO(multidisplay): Assume that such devices physical keys are on the main screen.
5619            final DisplayContent displayContent = getDefaultDisplayContentLocked();
5620            if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) {
5621                // On devices with a natural orientation of portrait
5622                switch (rotation) {
5623                    default:
5624                    case Surface.ROTATION_0:
5625                        return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
5626                    case Surface.ROTATION_90:
5627                        return Gravity.RIGHT | Gravity.BOTTOM;
5628                    case Surface.ROTATION_180:
5629                        return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
5630                    case Surface.ROTATION_270:
5631                        return Gravity.START | Gravity.BOTTOM;
5632                }
5633            }
5634
5635            // On devices with a natural orientation of landscape
5636            switch (rotation) {
5637                default:
5638                case Surface.ROTATION_0:
5639                    return Gravity.RIGHT | Gravity.BOTTOM;
5640                case Surface.ROTATION_90:
5641                    return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
5642                case Surface.ROTATION_180:
5643                    return Gravity.START | Gravity.BOTTOM;
5644                case Surface.ROTATION_270:
5645                    return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
5646            }
5647        }
5648    }
5649
5650    /**
5651     * Starts the view server on the specified port.
5652     *
5653     * @param port The port to listener to.
5654     *
5655     * @return True if the server was successfully started, false otherwise.
5656     *
5657     * @see com.android.server.wm.ViewServer
5658     * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT
5659     */
5660    @Override
5661    public boolean startViewServer(int port) {
5662        if (isSystemSecure()) {
5663            return false;
5664        }
5665
5666        if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) {
5667            return false;
5668        }
5669
5670        if (port < 1024) {
5671            return false;
5672        }
5673
5674        if (mViewServer != null) {
5675            if (!mViewServer.isRunning()) {
5676                try {
5677                    return mViewServer.start();
5678                } catch (IOException e) {
5679                    Slog.w(TAG, "View server did not start");
5680                }
5681            }
5682            return false;
5683        }
5684
5685        try {
5686            mViewServer = new ViewServer(this, port);
5687            return mViewServer.start();
5688        } catch (IOException e) {
5689            Slog.w(TAG, "View server did not start");
5690        }
5691        return false;
5692    }
5693
5694    private boolean isSystemSecure() {
5695        return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) &&
5696                "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
5697    }
5698
5699    /**
5700     * Stops the view server if it exists.
5701     *
5702     * @return True if the server stopped, false if it wasn't started or
5703     *         couldn't be stopped.
5704     *
5705     * @see com.android.server.wm.ViewServer
5706     */
5707    @Override
5708    public boolean stopViewServer() {
5709        if (isSystemSecure()) {
5710            return false;
5711        }
5712
5713        if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) {
5714            return false;
5715        }
5716
5717        if (mViewServer != null) {
5718            return mViewServer.stop();
5719        }
5720        return false;
5721    }
5722
5723    /**
5724     * Indicates whether the view server is running.
5725     *
5726     * @return True if the server is running, false otherwise.
5727     *
5728     * @see com.android.server.wm.ViewServer
5729     */
5730    @Override
5731    public boolean isViewServerRunning() {
5732        if (isSystemSecure()) {
5733            return false;
5734        }
5735
5736        if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) {
5737            return false;
5738        }
5739
5740        return mViewServer != null && mViewServer.isRunning();
5741    }
5742
5743    /**
5744     * Lists all availble windows in the system. The listing is written in the
5745     * specified Socket's output stream with the following syntax:
5746     * windowHashCodeInHexadecimal windowName
5747     * Each line of the ouput represents a different window.
5748     *
5749     * @param client The remote client to send the listing to.
5750     * @return False if an error occured, true otherwise.
5751     */
5752    boolean viewServerListWindows(Socket client) {
5753        if (isSystemSecure()) {
5754            return false;
5755        }
5756
5757        boolean result = true;
5758
5759        WindowList windows = new WindowList();
5760        synchronized (mWindowMap) {
5761            //noinspection unchecked
5762            DisplayContentsIterator iterator = new DisplayContentsIterator();
5763            while(iterator.hasNext()) {
5764                windows.addAll(iterator.next().getWindowList());
5765            }
5766        }
5767
5768        BufferedWriter out = null;
5769
5770        // Any uncaught exception will crash the system process
5771        try {
5772            OutputStream clientStream = client.getOutputStream();
5773            out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
5774
5775            final int count = windows.size();
5776            for (int i = 0; i < count; i++) {
5777                final WindowState w = windows.get(i);
5778                out.write(Integer.toHexString(System.identityHashCode(w)));
5779                out.write(' ');
5780                out.append(w.mAttrs.getTitle());
5781                out.write('\n');
5782            }
5783
5784            out.write("DONE.\n");
5785            out.flush();
5786        } catch (Exception e) {
5787            result = false;
5788        } finally {
5789            if (out != null) {
5790                try {
5791                    out.close();
5792                } catch (IOException e) {
5793                    result = false;
5794                }
5795            }
5796        }
5797
5798        return result;
5799    }
5800
5801    // TODO(multidisplay): Extend to multiple displays.
5802    /**
5803     * Returns the focused window in the following format:
5804     * windowHashCodeInHexadecimal windowName
5805     *
5806     * @param client The remote client to send the listing to.
5807     * @return False if an error occurred, true otherwise.
5808     */
5809    boolean viewServerGetFocusedWindow(Socket client) {
5810        if (isSystemSecure()) {
5811            return false;
5812        }
5813
5814        boolean result = true;
5815
5816        WindowState focusedWindow = getFocusedWindow();
5817
5818        BufferedWriter out = null;
5819
5820        // Any uncaught exception will crash the system process
5821        try {
5822            OutputStream clientStream = client.getOutputStream();
5823            out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
5824
5825            if(focusedWindow != null) {
5826                out.write(Integer.toHexString(System.identityHashCode(focusedWindow)));
5827                out.write(' ');
5828                out.append(focusedWindow.mAttrs.getTitle());
5829            }
5830            out.write('\n');
5831            out.flush();
5832        } catch (Exception e) {
5833            result = false;
5834        } finally {
5835            if (out != null) {
5836                try {
5837                    out.close();
5838                } catch (IOException e) {
5839                    result = false;
5840                }
5841            }
5842        }
5843
5844        return result;
5845    }
5846
5847    /**
5848     * Sends a command to a target window. The result of the command, if any, will be
5849     * written in the output stream of the specified socket.
5850     *
5851     * The parameters must follow this syntax:
5852     * windowHashcode extra
5853     *
5854     * Where XX is the length in characeters of the windowTitle.
5855     *
5856     * The first parameter is the target window. The window with the specified hashcode
5857     * will be the target. If no target can be found, nothing happens. The extra parameters
5858     * will be delivered to the target window and as parameters to the command itself.
5859     *
5860     * @param client The remote client to sent the result, if any, to.
5861     * @param command The command to execute.
5862     * @param parameters The command parameters.
5863     *
5864     * @return True if the command was successfully delivered, false otherwise. This does
5865     *         not indicate whether the command itself was successful.
5866     */
5867    boolean viewServerWindowCommand(Socket client, String command, String parameters) {
5868        if (isSystemSecure()) {
5869            return false;
5870        }
5871
5872        boolean success = true;
5873        Parcel data = null;
5874        Parcel reply = null;
5875
5876        BufferedWriter out = null;
5877
5878        // Any uncaught exception will crash the system process
5879        try {
5880            // Find the hashcode of the window
5881            int index = parameters.indexOf(' ');
5882            if (index == -1) {
5883                index = parameters.length();
5884            }
5885            final String code = parameters.substring(0, index);
5886            int hashCode = (int) Long.parseLong(code, 16);
5887
5888            // Extract the command's parameter after the window description
5889            if (index < parameters.length()) {
5890                parameters = parameters.substring(index + 1);
5891            } else {
5892                parameters = "";
5893            }
5894
5895            final WindowState window = findWindow(hashCode);
5896            if (window == null) {
5897                return false;
5898            }
5899
5900            data = Parcel.obtain();
5901            data.writeInterfaceToken("android.view.IWindow");
5902            data.writeString(command);
5903            data.writeString(parameters);
5904            data.writeInt(1);
5905            ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0);
5906
5907            reply = Parcel.obtain();
5908
5909            final IBinder binder = window.mClient.asBinder();
5910            // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER
5911            binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
5912
5913            reply.readException();
5914
5915            if (!client.isOutputShutdown()) {
5916                out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
5917                out.write("DONE\n");
5918                out.flush();
5919            }
5920
5921        } catch (Exception e) {
5922            Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e);
5923            success = false;
5924        } finally {
5925            if (data != null) {
5926                data.recycle();
5927            }
5928            if (reply != null) {
5929                reply.recycle();
5930            }
5931            if (out != null) {
5932                try {
5933                    out.close();
5934                } catch (IOException e) {
5935
5936                }
5937            }
5938        }
5939
5940        return success;
5941    }
5942
5943    public void addWindowChangeListener(WindowChangeListener listener) {
5944        synchronized(mWindowMap) {
5945            mWindowChangeListeners.add(listener);
5946        }
5947    }
5948
5949    public void removeWindowChangeListener(WindowChangeListener listener) {
5950        synchronized(mWindowMap) {
5951            mWindowChangeListeners.remove(listener);
5952        }
5953    }
5954
5955    private void notifyWindowsChanged() {
5956        WindowChangeListener[] windowChangeListeners;
5957        synchronized(mWindowMap) {
5958            if(mWindowChangeListeners.isEmpty()) {
5959                return;
5960            }
5961            windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
5962            windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
5963        }
5964        int N = windowChangeListeners.length;
5965        for(int i = 0; i < N; i++) {
5966            windowChangeListeners[i].windowsChanged();
5967        }
5968    }
5969
5970    private void notifyFocusChanged() {
5971        WindowChangeListener[] windowChangeListeners;
5972        synchronized(mWindowMap) {
5973            if(mWindowChangeListeners.isEmpty()) {
5974                return;
5975            }
5976            windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
5977            windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
5978        }
5979        int N = windowChangeListeners.length;
5980        for(int i = 0; i < N; i++) {
5981            windowChangeListeners[i].focusChanged();
5982        }
5983    }
5984
5985    private WindowState findWindow(int hashCode) {
5986        if (hashCode == -1) {
5987            // TODO(multidisplay): Extend to multiple displays.
5988            return getFocusedWindow();
5989        }
5990
5991        synchronized (mWindowMap) {
5992            mTmpWindowsIterator.reset(FORWARD_ITERATOR);
5993            while (mTmpWindowsIterator.hasNext()) {
5994                final WindowState w = mTmpWindowsIterator.next();
5995                if (System.identityHashCode(w) == hashCode) {
5996                    return w;
5997                }
5998            }
5999        }
6000
6001        return null;
6002    }
6003
6004    /*
6005     * Instruct the Activity Manager to fetch the current configuration and broadcast
6006     * that to config-changed listeners if appropriate.
6007     */
6008    void sendNewConfiguration() {
6009        try {
6010            mActivityManager.updateConfiguration(null);
6011        } catch (RemoteException e) {
6012        }
6013    }
6014
6015    public Configuration computeNewConfiguration() {
6016        synchronized (mWindowMap) {
6017            Configuration config = computeNewConfigurationLocked();
6018            if (config == null && mWaitingForConfig) {
6019                // Nothing changed but we are waiting for something... stop that!
6020                mWaitingForConfig = false;
6021                performLayoutAndPlaceSurfacesLocked();
6022            }
6023            return config;
6024        }
6025    }
6026
6027    Configuration computeNewConfigurationLocked() {
6028        Configuration config = new Configuration();
6029        config.fontScale = 0;
6030        if (!computeScreenConfigurationLocked(config)) {
6031            return null;
6032        }
6033        return config;
6034    }
6035
6036    private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int dw, int dh) {
6037        // TODO: Multidisplay: for now only use with default display.
6038        final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation);
6039        if (width < displayInfo.smallestNominalAppWidth) {
6040            displayInfo.smallestNominalAppWidth = width;
6041        }
6042        if (width > displayInfo.largestNominalAppWidth) {
6043            displayInfo.largestNominalAppWidth = width;
6044        }
6045        final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation);
6046        if (height < displayInfo.smallestNominalAppHeight) {
6047            displayInfo.smallestNominalAppHeight = height;
6048        }
6049        if (height > displayInfo.largestNominalAppHeight) {
6050            displayInfo.largestNominalAppHeight = height;
6051        }
6052    }
6053
6054    private int reduceConfigLayout(int curLayout, int rotation, float density,
6055            int dw, int dh) {
6056        // TODO: Multidisplay: for now only use with default display.
6057        // Get the app screen size at this rotation.
6058        int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation);
6059        int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation);
6060
6061        // Compute the screen layout size class for this rotation.
6062        int longSize = w;
6063        int shortSize = h;
6064        if (longSize < shortSize) {
6065            int tmp = longSize;
6066            longSize = shortSize;
6067            shortSize = tmp;
6068        }
6069        longSize = (int)(longSize/density);
6070        shortSize = (int)(shortSize/density);
6071        return Configuration.reduceScreenLayout(curLayout, longSize, shortSize);
6072    }
6073
6074    private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated,
6075                  int dw, int dh, float density, Configuration outConfig) {
6076        // TODO: Multidisplay: for now only use with default display.
6077
6078        // We need to determine the smallest width that will occur under normal
6079        // operation.  To this, start with the base screen size and compute the
6080        // width under the different possible rotations.  We need to un-rotate
6081        // the current screen dimensions before doing this.
6082        int unrotDw, unrotDh;
6083        if (rotated) {
6084            unrotDw = dh;
6085            unrotDh = dw;
6086        } else {
6087            unrotDw = dw;
6088            unrotDh = dh;
6089        }
6090        displayInfo.smallestNominalAppWidth = 1<<30;
6091        displayInfo.smallestNominalAppHeight = 1<<30;
6092        displayInfo.largestNominalAppWidth = 0;
6093        displayInfo.largestNominalAppHeight = 0;
6094        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, unrotDw, unrotDh);
6095        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, unrotDh, unrotDw);
6096        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, unrotDw, unrotDh);
6097        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, unrotDh, unrotDw);
6098        int sl = Configuration.resetScreenLayout(outConfig.screenLayout);
6099        sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh);
6100        sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw);
6101        sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh);
6102        sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw);
6103        outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density);
6104        outConfig.screenLayout = sl;
6105    }
6106
6107    private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm,
6108            int dw, int dh) {
6109        // TODO: Multidisplay: for now only use with default display.
6110        dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation);
6111        dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation);
6112        float scale = CompatibilityInfo.computeCompatibleScaling(dm, null);
6113        int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f);
6114        if (curSize == 0 || size < curSize) {
6115            curSize = size;
6116        }
6117        return curSize;
6118    }
6119
6120    private int computeCompatSmallestWidth(boolean rotated, DisplayMetrics dm, int dw, int dh) {
6121        // TODO: Multidisplay: for now only use with default display.
6122        mTmpDisplayMetrics.setTo(dm);
6123        final DisplayMetrics tmpDm = mTmpDisplayMetrics;
6124        final int unrotDw, unrotDh;
6125        if (rotated) {
6126            unrotDw = dh;
6127            unrotDh = dw;
6128        } else {
6129            unrotDw = dw;
6130            unrotDh = dh;
6131        }
6132        int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, tmpDm, unrotDw, unrotDh);
6133        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, tmpDm, unrotDh, unrotDw);
6134        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, tmpDm, unrotDw, unrotDh);
6135        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, tmpDm, unrotDh, unrotDw);
6136        return sw;
6137    }
6138
6139    boolean computeScreenConfigurationLocked(Configuration config) {
6140        if (!mDisplayReady) {
6141            return false;
6142        }
6143
6144        // TODO(multidisplay): For now, apply Configuration to main screen only.
6145        final DisplayContent displayContent = getDefaultDisplayContentLocked();
6146
6147        // Use the effective "visual" dimensions based on current rotation
6148        final boolean rotated = (mRotation == Surface.ROTATION_90
6149                || mRotation == Surface.ROTATION_270);
6150        final int realdw = rotated ?
6151                displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth;
6152        final int realdh = rotated ?
6153                displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight;
6154        int dw = realdw;
6155        int dh = realdh;
6156
6157        if (mAltOrientation) {
6158            if (realdw > realdh) {
6159                // Turn landscape into portrait.
6160                int maxw = (int)(realdh/1.3f);
6161                if (maxw < realdw) {
6162                    dw = maxw;
6163                }
6164            } else {
6165                // Turn portrait into landscape.
6166                int maxh = (int)(realdw/1.3f);
6167                if (maxh < realdh) {
6168                    dh = maxh;
6169                }
6170            }
6171        }
6172
6173        if (config != null) {
6174            config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT :
6175                    Configuration.ORIENTATION_LANDSCAPE;
6176        }
6177
6178        // Update application display metrics.
6179        final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation);
6180        final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation);
6181        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
6182        synchronized(displayContent.mDisplaySizeLock) {
6183            displayInfo.rotation = mRotation;
6184            displayInfo.logicalWidth = dw;
6185            displayInfo.logicalHeight = dh;
6186            displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity;
6187            displayInfo.appWidth = appWidth;
6188            displayInfo.appHeight = appHeight;
6189            displayInfo.getLogicalMetrics(mRealDisplayMetrics, null);
6190            displayInfo.getAppMetrics(mDisplayMetrics, null);
6191            mDisplayManagerService.setDisplayInfoOverrideFromWindowManager(
6192                    displayContent.getDisplayId(), displayInfo);
6193        }
6194        if (false) {
6195            Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight);
6196        }
6197
6198        final DisplayMetrics dm = mDisplayMetrics;
6199        mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm,
6200                mCompatDisplayMetrics);
6201
6202        if (config != null) {
6203            config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation)
6204                    / dm.density);
6205            config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation)
6206                    / dm.density);
6207            computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, dm.density, config);
6208
6209            config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale);
6210            config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale);
6211            config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh);
6212            config.densityDpi = displayContent.mBaseDisplayDensity;
6213
6214            // Update the configuration based on available input devices, lid switch,
6215            // and platform configuration.
6216            config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
6217            config.keyboard = Configuration.KEYBOARD_NOKEYS;
6218            config.navigation = Configuration.NAVIGATION_NONAV;
6219
6220            int keyboardPresence = 0;
6221            int navigationPresence = 0;
6222            final InputDevice[] devices = mInputManager.getInputDevices();
6223            final int len = devices.length;
6224            for (int i = 0; i < len; i++) {
6225                InputDevice device = devices[i];
6226                if (!device.isVirtual()) {
6227                    final int sources = device.getSources();
6228                    final int presenceFlag = device.isExternal() ?
6229                            WindowManagerPolicy.PRESENCE_EXTERNAL :
6230                                    WindowManagerPolicy.PRESENCE_INTERNAL;
6231
6232                    if (mIsTouchDevice) {
6233                        if ((sources & InputDevice.SOURCE_TOUCHSCREEN) ==
6234                                InputDevice.SOURCE_TOUCHSCREEN) {
6235                            config.touchscreen = Configuration.TOUCHSCREEN_FINGER;
6236                        }
6237                    } else {
6238                        config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
6239                    }
6240
6241                    if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) {
6242                        config.navigation = Configuration.NAVIGATION_TRACKBALL;
6243                        navigationPresence |= presenceFlag;
6244                    } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD
6245                            && config.navigation == Configuration.NAVIGATION_NONAV) {
6246                        config.navigation = Configuration.NAVIGATION_DPAD;
6247                        navigationPresence |= presenceFlag;
6248                    }
6249
6250                    if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {
6251                        config.keyboard = Configuration.KEYBOARD_QWERTY;
6252                        keyboardPresence |= presenceFlag;
6253                    }
6254                }
6255            }
6256
6257            // Determine whether a hard keyboard is available and enabled.
6258            boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS;
6259            if (hardKeyboardAvailable != mHardKeyboardAvailable) {
6260                mHardKeyboardAvailable = hardKeyboardAvailable;
6261                mHardKeyboardEnabled = hardKeyboardAvailable;
6262                mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
6263                mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
6264            }
6265            if (!mHardKeyboardEnabled) {
6266                config.keyboard = Configuration.KEYBOARD_NOKEYS;
6267            }
6268
6269            // Let the policy update hidden states.
6270            config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
6271            config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
6272            config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO;
6273            mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence);
6274        }
6275
6276        return true;
6277    }
6278
6279    public boolean isHardKeyboardAvailable() {
6280        synchronized (mWindowMap) {
6281            return mHardKeyboardAvailable;
6282        }
6283    }
6284
6285    public boolean isHardKeyboardEnabled() {
6286        synchronized (mWindowMap) {
6287            return mHardKeyboardEnabled;
6288        }
6289    }
6290
6291    public void setHardKeyboardEnabled(boolean enabled) {
6292        synchronized (mWindowMap) {
6293            if (mHardKeyboardEnabled != enabled) {
6294                mHardKeyboardEnabled = enabled;
6295                mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
6296            }
6297        }
6298    }
6299
6300    public void setOnHardKeyboardStatusChangeListener(
6301            OnHardKeyboardStatusChangeListener listener) {
6302        synchronized (mWindowMap) {
6303            mHardKeyboardStatusChangeListener = listener;
6304        }
6305    }
6306
6307    void notifyHardKeyboardStatusChange() {
6308        final boolean available, enabled;
6309        final OnHardKeyboardStatusChangeListener listener;
6310        synchronized (mWindowMap) {
6311            listener = mHardKeyboardStatusChangeListener;
6312            available = mHardKeyboardAvailable;
6313            enabled = mHardKeyboardEnabled;
6314        }
6315        if (listener != null) {
6316            listener.onHardKeyboardStatusChange(available, enabled);
6317        }
6318    }
6319
6320    // -------------------------------------------------------------
6321    // Drag and drop
6322    // -------------------------------------------------------------
6323
6324    IBinder prepareDragSurface(IWindow window, SurfaceSession session,
6325            int flags, int width, int height, Surface outSurface) {
6326        if (DEBUG_DRAG) {
6327            Slog.d(TAG, "prepare drag surface: w=" + width + " h=" + height
6328                    + " flags=" + Integer.toHexString(flags) + " win=" + window
6329                    + " asbinder=" + window.asBinder());
6330        }
6331
6332        final int callerPid = Binder.getCallingPid();
6333        final long origId = Binder.clearCallingIdentity();
6334        IBinder token = null;
6335
6336        try {
6337            synchronized (mWindowMap) {
6338                try {
6339                    if (mDragState == null) {
6340                        // TODO(multi-display): support other displays
6341                        final DisplayContent displayContent = getDefaultDisplayContentLocked();
6342                        final Display display = displayContent.getDisplay();
6343                        SurfaceControl surface = new SurfaceControl(session, "drag surface",
6344                                width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
6345                        surface.setLayerStack(display.getLayerStack());
6346                        if (SHOW_TRANSACTIONS) Slog.i(TAG, "  DRAG "
6347                                + surface + ": CREATE");
6348                        outSurface.copyFrom(surface);
6349                        final IBinder winBinder = window.asBinder();
6350                        token = new Binder();
6351                        mDragState = new DragState(this, token, surface, /*flags*/ 0, winBinder);
6352                        token = mDragState.mToken = new Binder();
6353
6354                        // 5 second timeout for this window to actually begin the drag
6355                        mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder);
6356                        Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder);
6357                        mH.sendMessageDelayed(msg, 5000);
6358                    } else {
6359                        Slog.w(TAG, "Drag already in progress");
6360                    }
6361                } catch (SurfaceControl.OutOfResourcesException e) {
6362                    Slog.e(TAG, "Can't allocate drag surface w=" + width + " h=" + height, e);
6363                    if (mDragState != null) {
6364                        mDragState.reset();
6365                        mDragState = null;
6366                    }
6367                }
6368            }
6369        } finally {
6370            Binder.restoreCallingIdentity(origId);
6371        }
6372
6373        return token;
6374    }
6375
6376    // -------------------------------------------------------------
6377    // Input Events and Focus Management
6378    // -------------------------------------------------------------
6379
6380    final InputMonitor mInputMonitor = new InputMonitor(this);
6381    private boolean mEventDispatchingEnabled;
6382
6383    @Override
6384    public void pauseKeyDispatching(IBinder _token) {
6385        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
6386                "pauseKeyDispatching()")) {
6387            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
6388        }
6389
6390        synchronized (mWindowMap) {
6391            WindowToken token = mTokenMap.get(_token);
6392            if (token != null) {
6393                mInputMonitor.pauseDispatchingLw(token);
6394            }
6395        }
6396    }
6397
6398    @Override
6399    public void resumeKeyDispatching(IBinder _token) {
6400        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
6401                "resumeKeyDispatching()")) {
6402            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
6403        }
6404
6405        synchronized (mWindowMap) {
6406            WindowToken token = mTokenMap.get(_token);
6407            if (token != null) {
6408                mInputMonitor.resumeDispatchingLw(token);
6409            }
6410        }
6411    }
6412
6413    @Override
6414    public void setEventDispatching(boolean enabled) {
6415        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
6416                "setEventDispatching()")) {
6417            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
6418        }
6419
6420        synchronized (mWindowMap) {
6421            mEventDispatchingEnabled = enabled;
6422            if (mDisplayEnabled) {
6423                mInputMonitor.setEventDispatchingLw(enabled);
6424            }
6425            sendScreenStatusToClientsLocked();
6426        }
6427    }
6428
6429    @Override
6430    public IBinder getFocusedWindowToken() {
6431        if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO,
6432                "getFocusedWindowToken()")) {
6433            throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission.");
6434        }
6435        synchronized (mWindowMap) {
6436            WindowState windowState = getFocusedWindowLocked();
6437            if (windowState != null) {
6438                return windowState.mClient.asBinder();
6439            }
6440            return null;
6441        }
6442    }
6443
6444    private WindowState getFocusedWindow() {
6445        synchronized (mWindowMap) {
6446            return getFocusedWindowLocked();
6447        }
6448    }
6449
6450    private WindowState getFocusedWindowLocked() {
6451        return mCurrentFocus;
6452    }
6453
6454    public boolean detectSafeMode() {
6455        if (!mInputMonitor.waitForInputDevicesReady(
6456                INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) {
6457            Slog.w(TAG, "Devices still not ready after waiting "
6458                   + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS
6459                   + " milliseconds before attempting to detect safe mode.");
6460        }
6461
6462        int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
6463                KeyEvent.KEYCODE_MENU);
6464        int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S);
6465        int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD,
6466                KeyEvent.KEYCODE_DPAD_CENTER);
6467        int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL,
6468                InputManagerService.BTN_MOUSE);
6469        int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
6470                KeyEvent.KEYCODE_VOLUME_DOWN);
6471        mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0
6472                || volumeDownState > 0;
6473        try {
6474            if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0) {
6475                mSafeMode = true;
6476                SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, "");
6477            }
6478        } catch (IllegalArgumentException e) {
6479        }
6480        if (mSafeMode) {
6481            Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState
6482                    + " dpad=" + dpadState + " trackball=" + trackballState + ")");
6483        } else {
6484            Log.i(TAG, "SAFE MODE not enabled");
6485        }
6486        mPolicy.setSafeMode(mSafeMode);
6487        return mSafeMode;
6488    }
6489
6490    public void displayReady() {
6491        displayReady(Display.DEFAULT_DISPLAY);
6492
6493        synchronized(mWindowMap) {
6494            final DisplayContent displayContent = getDefaultDisplayContentLocked();
6495            readForcedDisplaySizeAndDensityLocked(displayContent);
6496
6497            mDisplayReady = true;
6498            mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
6499                    PackageManager.FEATURE_TOUCHSCREEN);
6500
6501            mPolicy.setInitialDisplaySize(displayContent.getDisplay(),
6502                    displayContent.mInitialDisplayWidth,
6503                    displayContent.mInitialDisplayHeight,
6504                    displayContent.mInitialDisplayDensity);
6505        }
6506
6507        try {
6508            mActivityManager.updateConfiguration(null);
6509        } catch (RemoteException e) {
6510        }
6511    }
6512
6513    private void displayReady(int displayId) {
6514        synchronized(mWindowMap) {
6515            final DisplayContent displayContent = getDisplayContentLocked(displayId);
6516            if (displayContent != null) {
6517                mAnimator.addDisplayLocked(displayId);
6518                synchronized(displayContent.mDisplaySizeLock) {
6519                    // Bootstrap the default logical display from the display manager.
6520                    final DisplayInfo displayInfo = displayContent.getDisplayInfo();
6521                    DisplayInfo newDisplayInfo = mDisplayManagerService.getDisplayInfo(displayId);
6522                    if (newDisplayInfo != null) {
6523                        displayInfo.copyFrom(newDisplayInfo);
6524                    }
6525                    displayContent.mInitialDisplayWidth = displayInfo.logicalWidth;
6526                    displayContent.mInitialDisplayHeight = displayInfo.logicalHeight;
6527                    displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi;
6528                    displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth;
6529                    displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight;
6530                    displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity;
6531                }
6532            }
6533        }
6534    }
6535
6536    public void systemReady() {
6537        mPolicy.systemReady();
6538    }
6539
6540    // TODO(multidisplay): Call isScreenOn for each display.
6541    private void sendScreenStatusToClientsLocked() {
6542        final boolean on = mPowerManager.isScreenOn();
6543        mTmpWindowsIterator.reset(FORWARD_ITERATOR);
6544        while (mTmpWindowsIterator.hasNext()) {
6545            try {
6546                mTmpWindowsIterator.next().mClient.dispatchScreenState(on);
6547            } catch (RemoteException e) {
6548                // Ignored
6549            }
6550        }
6551    }
6552
6553    // -------------------------------------------------------------
6554    // Async Handler
6555    // -------------------------------------------------------------
6556
6557    final class H extends Handler {
6558        public static final int REPORT_FOCUS_CHANGE = 2;
6559        public static final int REPORT_LOSING_FOCUS = 3;
6560        public static final int DO_TRAVERSAL = 4;
6561        public static final int ADD_STARTING = 5;
6562        public static final int REMOVE_STARTING = 6;
6563        public static final int FINISHED_STARTING = 7;
6564        public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8;
6565        public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9;
6566        public static final int WINDOW_FREEZE_TIMEOUT = 11;
6567
6568        public static final int APP_TRANSITION_TIMEOUT = 13;
6569        public static final int PERSIST_ANIMATION_SCALE = 14;
6570        public static final int FORCE_GC = 15;
6571        public static final int ENABLE_SCREEN = 16;
6572        public static final int APP_FREEZE_TIMEOUT = 17;
6573        public static final int SEND_NEW_CONFIGURATION = 18;
6574        public static final int REPORT_WINDOWS_CHANGE = 19;
6575        public static final int DRAG_START_TIMEOUT = 20;
6576        public static final int DRAG_END_TIMEOUT = 21;
6577        public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22;
6578        public static final int BOOT_TIMEOUT = 23;
6579        public static final int WAITING_FOR_DRAWN_TIMEOUT = 24;
6580        public static final int SHOW_STRICT_MODE_VIOLATION = 25;
6581        public static final int DO_ANIMATION_CALLBACK = 26;
6582
6583        public static final int DO_DISPLAY_ADDED = 27;
6584        public static final int DO_DISPLAY_REMOVED = 28;
6585        public static final int DO_DISPLAY_CHANGED = 29;
6586
6587        public static final int CLIENT_FREEZE_TIMEOUT = 30;
6588
6589        @Override
6590        public void handleMessage(Message msg) {
6591            if (DEBUG_WINDOW_TRACE) {
6592                Slog.v(TAG, "handleMessage: entry what=" + msg.what);
6593            }
6594            switch (msg.what) {
6595                case REPORT_FOCUS_CHANGE: {
6596                    WindowState lastFocus;
6597                    WindowState newFocus;
6598
6599                    synchronized(mWindowMap) {
6600                        lastFocus = mLastFocus;
6601                        newFocus = mCurrentFocus;
6602                        if (lastFocus == newFocus) {
6603                            // Focus is not changing, so nothing to do.
6604                            return;
6605                        }
6606                        mLastFocus = newFocus;
6607                        //Slog.i(TAG, "Focus moving from " + lastFocus
6608                        //        + " to " + newFocus);
6609                        if (newFocus != null && lastFocus != null
6610                                && !newFocus.isDisplayedLw()) {
6611                            //Slog.i(TAG, "Delaying loss of focus...");
6612                            mLosingFocus.add(lastFocus);
6613                            lastFocus = null;
6614                        }
6615                    }
6616
6617                    if (lastFocus != newFocus) {
6618                        //System.out.println("Changing focus from " + lastFocus
6619                        //                   + " to " + newFocus);
6620                        if (newFocus != null) {
6621                            try {
6622                                //Slog.i(TAG, "Gaining focus: " + newFocus);
6623                                newFocus.mClient.windowFocusChanged(true, mInTouchMode);
6624                            } catch (RemoteException e) {
6625                                // Ignore if process has died.
6626                            }
6627                            notifyFocusChanged();
6628                        }
6629
6630                        if (lastFocus != null) {
6631                            try {
6632                                //Slog.i(TAG, "Losing focus: " + lastFocus);
6633                                lastFocus.mClient.windowFocusChanged(false, mInTouchMode);
6634                            } catch (RemoteException e) {
6635                                // Ignore if process has died.
6636                            }
6637                        }
6638                    }
6639                } break;
6640
6641                case REPORT_LOSING_FOCUS: {
6642                    ArrayList<WindowState> losers;
6643
6644                    synchronized(mWindowMap) {
6645                        losers = mLosingFocus;
6646                        mLosingFocus = new ArrayList<WindowState>();
6647                    }
6648
6649                    final int N = losers.size();
6650                    for (int i=0; i<N; i++) {
6651                        try {
6652                            //Slog.i(TAG, "Losing delayed focus: " + losers.get(i));
6653                            losers.get(i).mClient.windowFocusChanged(false, mInTouchMode);
6654                        } catch (RemoteException e) {
6655                             // Ignore if process has died.
6656                        }
6657                    }
6658                } break;
6659
6660                case DO_TRAVERSAL: {
6661                    synchronized(mWindowMap) {
6662                        mTraversalScheduled = false;
6663                        performLayoutAndPlaceSurfacesLocked();
6664                    }
6665                } break;
6666
6667                case ADD_STARTING: {
6668                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
6669                    final StartingData sd = wtoken.startingData;
6670
6671                    if (sd == null) {
6672                        // Animation has been canceled... do nothing.
6673                        return;
6674                    }
6675
6676                    if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting "
6677                            + wtoken + ": pkg=" + sd.pkg);
6678
6679                    View view = null;
6680                    try {
6681                        view = mPolicy.addStartingWindow(
6682                            wtoken.token, sd.pkg, sd.theme, sd.compatInfo,
6683                            sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.windowFlags);
6684                    } catch (Exception e) {
6685                        Slog.w(TAG, "Exception when adding starting window", e);
6686                    }
6687
6688                    if (view != null) {
6689                        boolean abort = false;
6690
6691                        synchronized(mWindowMap) {
6692                            if (wtoken.removed || wtoken.startingData == null) {
6693                                // If the window was successfully added, then
6694                                // we need to remove it.
6695                                if (wtoken.startingWindow != null) {
6696                                    if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
6697                                            "Aborted starting " + wtoken
6698                                            + ": removed=" + wtoken.removed
6699                                            + " startingData=" + wtoken.startingData);
6700                                    wtoken.startingWindow = null;
6701                                    wtoken.startingData = null;
6702                                    abort = true;
6703                                }
6704                            } else {
6705                                wtoken.startingView = view;
6706                            }
6707                            if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG,
6708                                    "Added starting " + wtoken
6709                                    + ": startingWindow="
6710                                    + wtoken.startingWindow + " startingView="
6711                                    + wtoken.startingView);
6712                        }
6713
6714                        if (abort) {
6715                            try {
6716                                mPolicy.removeStartingWindow(wtoken.token, view);
6717                            } catch (Exception e) {
6718                                Slog.w(TAG, "Exception when removing starting window", e);
6719                            }
6720                        }
6721                    }
6722                } break;
6723
6724                case REMOVE_STARTING: {
6725                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
6726                    IBinder token = null;
6727                    View view = null;
6728                    synchronized (mWindowMap) {
6729                        if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting "
6730                                + wtoken + ": startingWindow="
6731                                + wtoken.startingWindow + " startingView="
6732                                + wtoken.startingView);
6733                        if (wtoken.startingWindow != null) {
6734                            view = wtoken.startingView;
6735                            token = wtoken.token;
6736                            wtoken.startingData = null;
6737                            wtoken.startingView = null;
6738                            wtoken.startingWindow = null;
6739                            wtoken.startingDisplayed = false;
6740                        }
6741                    }
6742                    if (view != null) {
6743                        try {
6744                            mPolicy.removeStartingWindow(token, view);
6745                        } catch (Exception e) {
6746                            Slog.w(TAG, "Exception when removing starting window", e);
6747                        }
6748                    }
6749                } break;
6750
6751                case FINISHED_STARTING: {
6752                    IBinder token = null;
6753                    View view = null;
6754                    while (true) {
6755                        synchronized (mWindowMap) {
6756                            final int N = mFinishedStarting.size();
6757                            if (N <= 0) {
6758                                break;
6759                            }
6760                            AppWindowToken wtoken = mFinishedStarting.remove(N-1);
6761
6762                            if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
6763                                    "Finished starting " + wtoken
6764                                    + ": startingWindow=" + wtoken.startingWindow
6765                                    + " startingView=" + wtoken.startingView);
6766
6767                            if (wtoken.startingWindow == null) {
6768                                continue;
6769                            }
6770
6771                            view = wtoken.startingView;
6772                            token = wtoken.token;
6773                            wtoken.startingData = null;
6774                            wtoken.startingView = null;
6775                            wtoken.startingWindow = null;
6776                            wtoken.startingDisplayed = false;
6777                        }
6778
6779                        try {
6780                            mPolicy.removeStartingWindow(token, view);
6781                        } catch (Exception e) {
6782                            Slog.w(TAG, "Exception when removing starting window", e);
6783                        }
6784                    }
6785                } break;
6786
6787                case REPORT_APPLICATION_TOKEN_DRAWN: {
6788                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
6789
6790                    try {
6791                        if (DEBUG_VISIBILITY) Slog.v(
6792                                TAG, "Reporting drawn in " + wtoken);
6793                        wtoken.appToken.windowsDrawn();
6794                    } catch (RemoteException ex) {
6795                    }
6796                } break;
6797
6798                case REPORT_APPLICATION_TOKEN_WINDOWS: {
6799                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
6800
6801                    boolean nowVisible = msg.arg1 != 0;
6802                    boolean nowGone = msg.arg2 != 0;
6803
6804                    try {
6805                        if (DEBUG_VISIBILITY) Slog.v(
6806                                TAG, "Reporting visible in " + wtoken
6807                                + " visible=" + nowVisible
6808                                + " gone=" + nowGone);
6809                        if (nowVisible) {
6810                            wtoken.appToken.windowsVisible();
6811                        } else {
6812                            wtoken.appToken.windowsGone();
6813                        }
6814                    } catch (RemoteException ex) {
6815                    }
6816                } break;
6817
6818                case WINDOW_FREEZE_TIMEOUT: {
6819                    // TODO(multidisplay): Can non-default displays rotate?
6820                    synchronized (mWindowMap) {
6821                        Slog.w(TAG, "Window freeze timeout expired.");
6822                        final WindowList windows = getDefaultWindowListLocked();
6823                        int i = windows.size();
6824                        while (i > 0) {
6825                            i--;
6826                            WindowState w = windows.get(i);
6827                            if (w.mOrientationChanging) {
6828                                w.mOrientationChanging = false;
6829                                Slog.w(TAG, "Force clearing orientation change: " + w);
6830                            }
6831                        }
6832                        performLayoutAndPlaceSurfacesLocked();
6833                    }
6834                    break;
6835                }
6836
6837                case APP_TRANSITION_TIMEOUT: {
6838                    synchronized (mWindowMap) {
6839                        if (mAppTransition.isTransitionSet()) {
6840                            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** APP TRANSITION TIMEOUT");
6841                            mAppTransition.setTimeout();
6842                            performLayoutAndPlaceSurfacesLocked();
6843                        }
6844                    }
6845                    break;
6846                }
6847
6848                case PERSIST_ANIMATION_SCALE: {
6849                    Settings.Global.putFloat(mContext.getContentResolver(),
6850                            Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
6851                    Settings.Global.putFloat(mContext.getContentResolver(),
6852                            Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
6853                    Settings.Global.putFloat(mContext.getContentResolver(),
6854                            Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScale);
6855                    break;
6856                }
6857
6858                case FORCE_GC: {
6859                    synchronized (mWindowMap) {
6860                        // Since we're holding both mWindowMap and mAnimator we don't need to
6861                        // hold mAnimator.mLayoutToAnim.
6862                        if (mAnimator.mAnimating || mAnimationScheduled) {
6863                            // If we are animating, don't do the gc now but
6864                            // delay a bit so we don't interrupt the animation.
6865                            sendEmptyMessageDelayed(H.FORCE_GC, 2000);
6866                            return;
6867                        }
6868                        // If we are currently rotating the display, it will
6869                        // schedule a new message when done.
6870                        if (mDisplayFrozen) {
6871                            return;
6872                        }
6873                    }
6874                    Runtime.getRuntime().gc();
6875                    break;
6876                }
6877
6878                case ENABLE_SCREEN: {
6879                    performEnableScreen();
6880                    break;
6881                }
6882
6883                case APP_FREEZE_TIMEOUT: {
6884                    synchronized (mWindowMap) {
6885                        Slog.w(TAG, "App freeze timeout expired.");
6886                        DisplayContent displayContent = getDefaultDisplayContentLocked();
6887                        AppTokenIterator iterator =
6888                                displayContent.getTmpAppIterator(REVERSE_ITERATOR);
6889                        while (iterator.hasNext()) {
6890                            AppWindowToken tok = iterator.next();
6891                            if (tok.mAppAnimator.freezingScreen) {
6892                                Slog.w(TAG, "Force clearing freeze: " + tok);
6893                                unsetAppFreezingScreenLocked(tok, true, true);
6894                            }
6895                        }
6896                    }
6897                    break;
6898                }
6899
6900                case CLIENT_FREEZE_TIMEOUT: {
6901                    synchronized (mWindowMap) {
6902                        if (mClientFreezingScreen) {
6903                            mClientFreezingScreen = false;
6904                            stopFreezingDisplayLocked();
6905                        }
6906                    }
6907                    break;
6908                }
6909
6910                case SEND_NEW_CONFIGURATION: {
6911                    removeMessages(SEND_NEW_CONFIGURATION);
6912                    sendNewConfiguration();
6913                    break;
6914                }
6915
6916                case REPORT_WINDOWS_CHANGE: {
6917                    if (mWindowsChanged) {
6918                        synchronized (mWindowMap) {
6919                            mWindowsChanged = false;
6920                        }
6921                        notifyWindowsChanged();
6922                    }
6923                    break;
6924                }
6925
6926                case DRAG_START_TIMEOUT: {
6927                    IBinder win = (IBinder)msg.obj;
6928                    if (DEBUG_DRAG) {
6929                        Slog.w(TAG, "Timeout starting drag by win " + win);
6930                    }
6931                    synchronized (mWindowMap) {
6932                        // !!! TODO: ANR the app that has failed to start the drag in time
6933                        if (mDragState != null) {
6934                            mDragState.unregister();
6935                            mInputMonitor.updateInputWindowsLw(true /*force*/);
6936                            mDragState.reset();
6937                            mDragState = null;
6938                        }
6939                    }
6940                    break;
6941                }
6942
6943                case DRAG_END_TIMEOUT: {
6944                    IBinder win = (IBinder)msg.obj;
6945                    if (DEBUG_DRAG) {
6946                        Slog.w(TAG, "Timeout ending drag to win " + win);
6947                    }
6948                    synchronized (mWindowMap) {
6949                        // !!! TODO: ANR the drag-receiving app
6950                        if (mDragState != null) {
6951                            mDragState.mDragResult = false;
6952                            mDragState.endDragLw();
6953                        }
6954                    }
6955                    break;
6956                }
6957
6958                case REPORT_HARD_KEYBOARD_STATUS_CHANGE: {
6959                    notifyHardKeyboardStatusChange();
6960                    break;
6961                }
6962
6963                case BOOT_TIMEOUT: {
6964                    performBootTimeout();
6965                    break;
6966                }
6967
6968                case WAITING_FOR_DRAWN_TIMEOUT: {
6969                    Pair<WindowState, IRemoteCallback> pair;
6970                    synchronized (mWindowMap) {
6971                        pair = (Pair<WindowState, IRemoteCallback>)msg.obj;
6972                        Slog.w(TAG, "Timeout waiting for drawn: " + pair.first);
6973                        if (!mWaitingForDrawn.remove(pair)) {
6974                            return;
6975                        }
6976                    }
6977                    try {
6978                        pair.second.sendResult(null);
6979                    } catch (RemoteException e) {
6980                    }
6981                    break;
6982                }
6983
6984                case SHOW_STRICT_MODE_VIOLATION: {
6985                    showStrictModeViolation(msg.arg1, msg.arg2);
6986                    break;
6987                }
6988
6989                case DO_ANIMATION_CALLBACK: {
6990                    try {
6991                        ((IRemoteCallback)msg.obj).sendResult(null);
6992                    } catch (RemoteException e) {
6993                    }
6994                    break;
6995                }
6996
6997                case DO_DISPLAY_ADDED:
6998                    synchronized (mWindowMap) {
6999                        handleDisplayAddedLocked(msg.arg1);
7000                    }
7001                    break;
7002
7003                case DO_DISPLAY_REMOVED:
7004                    synchronized (mWindowMap) {
7005                        handleDisplayRemovedLocked(msg.arg1);
7006                    }
7007                    break;
7008
7009                case DO_DISPLAY_CHANGED:
7010                    synchronized (mWindowMap) {
7011                        handleDisplayChangedLocked(msg.arg1);
7012                    }
7013                    break;
7014            }
7015            if (DEBUG_WINDOW_TRACE) {
7016                Slog.v(TAG, "handleMessage: exit");
7017            }
7018        }
7019    }
7020
7021    // -------------------------------------------------------------
7022    // IWindowManager API
7023    // -------------------------------------------------------------
7024
7025    @Override
7026    public IWindowSession openSession(IInputMethodClient client,
7027            IInputContext inputContext) {
7028        if (client == null) throw new IllegalArgumentException("null client");
7029        if (inputContext == null) throw new IllegalArgumentException("null inputContext");
7030        Session session = new Session(this, client, inputContext);
7031        return session;
7032    }
7033
7034    @Override
7035    public boolean inputMethodClientHasFocus(IInputMethodClient client) {
7036        synchronized (mWindowMap) {
7037            // The focus for the client is the window immediately below
7038            // where we would place the input method window.
7039            int idx = findDesiredInputMethodWindowIndexLocked(false);
7040            if (idx > 0) {
7041                // TODO(multidisplay): IMEs are only supported on the default display.
7042                WindowState imFocus = getDefaultWindowListLocked().get(idx-1);
7043                if (DEBUG_INPUT_METHOD) {
7044                    Slog.i(TAG, "Desired input method target: " + imFocus);
7045                    Slog.i(TAG, "Current focus: " + mCurrentFocus);
7046                    Slog.i(TAG, "Last focus: " + mLastFocus);
7047                }
7048                if (imFocus != null) {
7049                    // This may be a starting window, in which case we still want
7050                    // to count it as okay.
7051                    if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING
7052                            && imFocus.mAppToken != null) {
7053                        // The client has definitely started, so it really should
7054                        // have a window in this app token.  Let's look for it.
7055                        for (int i=0; i<imFocus.mAppToken.windows.size(); i++) {
7056                            WindowState w = imFocus.mAppToken.windows.get(i);
7057                            if (w != imFocus) {
7058                                Log.i(TAG, "Switching to real app window: " + w);
7059                                imFocus = w;
7060                                break;
7061                            }
7062                        }
7063                    }
7064                    if (DEBUG_INPUT_METHOD) {
7065                        Slog.i(TAG, "IM target client: " + imFocus.mSession.mClient);
7066                        if (imFocus.mSession.mClient != null) {
7067                            Slog.i(TAG, "IM target client binder: "
7068                                    + imFocus.mSession.mClient.asBinder());
7069                            Slog.i(TAG, "Requesting client binder: " + client.asBinder());
7070                        }
7071                    }
7072                    if (imFocus.mSession.mClient != null &&
7073                            imFocus.mSession.mClient.asBinder() == client.asBinder()) {
7074                        return true;
7075                    }
7076                }
7077            }
7078
7079            // Okay, how about this...  what is the current focus?
7080            // It seems in some cases we may not have moved the IM
7081            // target window, such as when it was in a pop-up window,
7082            // so let's also look at the current focus.  (An example:
7083            // go to Gmail, start searching so the keyboard goes up,
7084            // press home.  Sometimes the IME won't go down.)
7085            // Would be nice to fix this more correctly, but it's
7086            // way at the end of a release, and this should be good enough.
7087            if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null
7088                    && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) {
7089                return true;
7090            }
7091        }
7092        return false;
7093    }
7094
7095    public void getInitialDisplaySize(int displayId, Point size) {
7096        synchronized (mWindowMap) {
7097            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7098            if (displayContent != null) {
7099                synchronized(displayContent.mDisplaySizeLock) {
7100                    size.x = displayContent.mInitialDisplayWidth;
7101                    size.y = displayContent.mInitialDisplayHeight;
7102                }
7103            }
7104        }
7105    }
7106
7107    @Override
7108    public void setForcedDisplaySize(int displayId, int width, int height) {
7109        if (mContext.checkCallingOrSelfPermission(
7110                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7111                PackageManager.PERMISSION_GRANTED) {
7112            throw new SecurityException("Must hold permission " +
7113                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
7114        }
7115        if (displayId != Display.DEFAULT_DISPLAY) {
7116            throw new IllegalArgumentException("Can only set the default display");
7117        }
7118        synchronized(mWindowMap) {
7119            // Set some sort of reasonable bounds on the size of the display that we
7120            // will try to emulate.
7121            final int MIN_WIDTH = 200;
7122            final int MIN_HEIGHT = 200;
7123            final int MAX_SCALE = 2;
7124            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7125            if (displayContent != null) {
7126                width = Math.min(Math.max(width, MIN_WIDTH),
7127                        displayContent.mInitialDisplayWidth * MAX_SCALE);
7128                height = Math.min(Math.max(height, MIN_HEIGHT),
7129                        displayContent.mInitialDisplayHeight * MAX_SCALE);
7130                setForcedDisplaySizeLocked(displayContent, width, height);
7131                Settings.Global.putString(mContext.getContentResolver(),
7132                        Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height);
7133            }
7134        }
7135    }
7136
7137    private void readForcedDisplaySizeAndDensityLocked(final DisplayContent displayContent) {
7138        final String sizeStr = Settings.Global.getString(mContext.getContentResolver(),
7139                Settings.Global.DISPLAY_SIZE_FORCED);
7140        if (sizeStr != null && sizeStr.length() > 0) {
7141            final int pos = sizeStr.indexOf(',');
7142            if (pos > 0 && sizeStr.lastIndexOf(',') == pos) {
7143                int width, height;
7144                try {
7145                    width = Integer.parseInt(sizeStr.substring(0, pos));
7146                    height = Integer.parseInt(sizeStr.substring(pos+1));
7147                    synchronized(displayContent.mDisplaySizeLock) {
7148                        if (displayContent.mBaseDisplayWidth != width
7149                                || displayContent.mBaseDisplayHeight != height) {
7150                            Slog.i(TAG, "FORCED DISPLAY SIZE: " + width + "x" + height);
7151                            displayContent.mBaseDisplayWidth = width;
7152                            displayContent.mBaseDisplayHeight = height;
7153                        }
7154                    }
7155                } catch (NumberFormatException ex) {
7156                }
7157            }
7158        }
7159        final String densityStr = Settings.Global.getString(mContext.getContentResolver(),
7160                Settings.Global.DISPLAY_DENSITY_FORCED);
7161        if (densityStr != null && densityStr.length() > 0) {
7162            int density;
7163            try {
7164                density = Integer.parseInt(densityStr);
7165                synchronized(displayContent.mDisplaySizeLock) {
7166                    if (displayContent.mBaseDisplayDensity != density) {
7167                        Slog.i(TAG, "FORCED DISPLAY DENSITY: " + density);
7168                        displayContent.mBaseDisplayDensity = density;
7169                    }
7170                }
7171            } catch (NumberFormatException ex) {
7172            }
7173        }
7174    }
7175
7176    // displayContent must not be null
7177    private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {
7178        Slog.i(TAG, "Using new display size: " + width + "x" + height);
7179
7180        synchronized(displayContent.mDisplaySizeLock) {
7181            displayContent.mBaseDisplayWidth = width;
7182            displayContent.mBaseDisplayHeight = height;
7183        }
7184        reconfigureDisplayLocked(displayContent);
7185    }
7186
7187    @Override
7188    public void clearForcedDisplaySize(int displayId) {
7189        if (mContext.checkCallingOrSelfPermission(
7190                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7191                PackageManager.PERMISSION_GRANTED) {
7192            throw new SecurityException("Must hold permission " +
7193                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
7194        }
7195        if (displayId != Display.DEFAULT_DISPLAY) {
7196            throw new IllegalArgumentException("Can only set the default display");
7197        }
7198        synchronized(mWindowMap) {
7199            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7200            if (displayContent != null) {
7201                setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
7202                        displayContent.mInitialDisplayHeight);
7203                Settings.Global.putString(mContext.getContentResolver(),
7204                        Settings.Global.DISPLAY_SIZE_FORCED, "");
7205            }
7206        }
7207    }
7208
7209    @Override
7210    public void setForcedDisplayDensity(int displayId, int density) {
7211        if (mContext.checkCallingOrSelfPermission(
7212                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7213                PackageManager.PERMISSION_GRANTED) {
7214            throw new SecurityException("Must hold permission " +
7215                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
7216        }
7217        if (displayId != Display.DEFAULT_DISPLAY) {
7218            throw new IllegalArgumentException("Can only set the default display");
7219        }
7220        synchronized(mWindowMap) {
7221            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7222            if (displayContent != null) {
7223                setForcedDisplayDensityLocked(displayContent, density);
7224                Settings.Global.putString(mContext.getContentResolver(),
7225                        Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density));
7226            }
7227        }
7228    }
7229
7230    // displayContent must not be null
7231    private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) {
7232        Slog.i(TAG, "Using new display density: " + density);
7233
7234        synchronized(displayContent.mDisplaySizeLock) {
7235            displayContent.mBaseDisplayDensity = density;
7236        }
7237        reconfigureDisplayLocked(displayContent);
7238    }
7239
7240    @Override
7241    public void clearForcedDisplayDensity(int displayId) {
7242        if (mContext.checkCallingOrSelfPermission(
7243                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7244                PackageManager.PERMISSION_GRANTED) {
7245            throw new SecurityException("Must hold permission " +
7246                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
7247        }
7248        if (displayId != Display.DEFAULT_DISPLAY) {
7249            throw new IllegalArgumentException("Can only set the default display");
7250        }
7251        synchronized(mWindowMap) {
7252            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7253            if (displayContent != null) {
7254                setForcedDisplayDensityLocked(displayContent, displayContent.mInitialDisplayDensity);
7255                Settings.Global.putString(mContext.getContentResolver(),
7256                        Settings.Global.DISPLAY_DENSITY_FORCED, "");
7257            }
7258        }
7259    }
7260
7261    // displayContent must not be null
7262    private void reconfigureDisplayLocked(DisplayContent displayContent) {
7263        // TODO: Multidisplay: for now only use with default display.
7264        mPolicy.setInitialDisplaySize(displayContent.getDisplay(),
7265                displayContent.mBaseDisplayWidth,
7266                displayContent.mBaseDisplayHeight,
7267                displayContent.mBaseDisplayDensity);
7268
7269        displayContent.layoutNeeded = true;
7270
7271        boolean configChanged = updateOrientationFromAppTokensLocked(false);
7272        mTempConfiguration.setToDefaults();
7273        mTempConfiguration.fontScale = mCurConfiguration.fontScale;
7274        if (computeScreenConfigurationLocked(mTempConfiguration)) {
7275            if (mCurConfiguration.diff(mTempConfiguration) != 0) {
7276                configChanged = true;
7277            }
7278        }
7279
7280        if (configChanged) {
7281            mWaitingForConfig = true;
7282            startFreezingDisplayLocked(false, 0, 0);
7283            mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
7284        }
7285
7286        performLayoutAndPlaceSurfacesLocked();
7287    }
7288
7289    public void setOverscan(int displayId, int left, int top, int right, int bottom) {
7290        if (mContext.checkCallingOrSelfPermission(
7291                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7292                PackageManager.PERMISSION_GRANTED) {
7293            throw new SecurityException("Must hold permission " +
7294                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
7295        }
7296        synchronized(mWindowMap) {
7297            DisplayContent displayContent = getDisplayContentLocked(displayId);
7298            if (displayContent != null) {
7299                mDisplayManagerService.setOverscan(displayId, left, top, right, bottom);
7300                final DisplayInfo displayInfo = displayContent.getDisplayInfo();
7301                synchronized(displayContent.mDisplaySizeLock) {
7302                    displayInfo.overscanLeft = left;
7303                    displayInfo.overscanTop = top;
7304                    displayInfo.overscanRight = right;
7305                    displayInfo.overscanBottom = bottom;
7306                }
7307                mPolicy.setDisplayOverscan(displayContent.getDisplay(), left, top, right, bottom);
7308                displayContent.layoutNeeded = true;
7309                mDisplaySettings.setOverscanLocked(displayInfo.name, left, top, right, bottom);
7310                mDisplaySettings.writeSettingsLocked();
7311                performLayoutAndPlaceSurfacesLocked();
7312            }
7313        }
7314    }
7315
7316    @Override
7317    public boolean hasSystemNavBar() {
7318        return mPolicy.hasSystemNavBar();
7319    }
7320
7321    // -------------------------------------------------------------
7322    // Internals
7323    // -------------------------------------------------------------
7324
7325    final WindowState windowForClientLocked(Session session, IWindow client,
7326            boolean throwOnError) {
7327        return windowForClientLocked(session, client.asBinder(), throwOnError);
7328    }
7329
7330    final WindowState windowForClientLocked(Session session, IBinder client,
7331            boolean throwOnError) {
7332        WindowState win = mWindowMap.get(client);
7333        if (localLOGV) Slog.v(
7334            TAG, "Looking up client " + client + ": " + win);
7335        if (win == null) {
7336            RuntimeException ex = new IllegalArgumentException(
7337                    "Requested window " + client + " does not exist");
7338            if (throwOnError) {
7339                throw ex;
7340            }
7341            Slog.w(TAG, "Failed looking up window", ex);
7342            return null;
7343        }
7344        if (session != null && win.mSession != session) {
7345            RuntimeException ex = new IllegalArgumentException(
7346                    "Requested window " + client + " is in session " +
7347                    win.mSession + ", not " + session);
7348            if (throwOnError) {
7349                throw ex;
7350            }
7351            Slog.w(TAG, "Failed looking up window", ex);
7352            return null;
7353        }
7354
7355        return win;
7356    }
7357
7358    final void rebuildAppWindowListLocked() {
7359        DisplayContentsIterator iterator = new DisplayContentsIterator();
7360        while (iterator.hasNext()) {
7361            rebuildAppWindowListLocked(iterator.next());
7362        }
7363    }
7364
7365    private void rebuildAppWindowListLocked(final DisplayContent displayContent) {
7366        final WindowList windows = displayContent.getWindowList();
7367        int NW = windows.size();
7368        int i;
7369        int lastBelow = -1;
7370        int numRemoved = 0;
7371
7372        if (mRebuildTmp.length < NW) {
7373            mRebuildTmp = new WindowState[NW+10];
7374        }
7375
7376        // First remove all existing app windows.
7377        i=0;
7378        while (i < NW) {
7379            WindowState w = windows.get(i);
7380            if (w.mAppToken != null) {
7381                WindowState win = windows.remove(i);
7382                win.mRebuilding = true;
7383                mRebuildTmp[numRemoved] = win;
7384                mWindowsChanged = true;
7385                if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
7386                        "Rebuild removing window: " + win);
7387                NW--;
7388                numRemoved++;
7389                continue;
7390            } else if (lastBelow == i-1) {
7391                if (w.mAttrs.type == TYPE_WALLPAPER || w.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
7392                    lastBelow = i;
7393                }
7394            }
7395            i++;
7396        }
7397
7398        // Keep whatever windows were below the app windows still below,
7399        // by skipping them.
7400        lastBelow++;
7401        i = lastBelow;
7402
7403        // First add all of the exiting app tokens...  these are no longer
7404        // in the main app list, but still have windows shown.  We put them
7405        // in the back because now that the animation is over we no longer
7406        // will care about them.
7407        AppTokenList exitingAppTokens = displayContent.mExitingAppTokens;
7408        int NT = exitingAppTokens.size();
7409        for (int j=0; j<NT; j++) {
7410            i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j));
7411        }
7412
7413        // And add in the still active app tokens in Z order.
7414        AppTokenIterator iterator = displayContent.getTmpAppIterator(FORWARD_ITERATOR);
7415        while (iterator.hasNext()) {
7416            i = reAddAppWindowsLocked(displayContent, i, iterator.next());
7417        }
7418
7419        i -= lastBelow;
7420        if (i != numRemoved) {
7421            Slog.w(TAG, "Rebuild removed " + numRemoved
7422                    + " windows but added " + i);
7423            for (i=0; i<numRemoved; i++) {
7424                WindowState ws = mRebuildTmp[i];
7425                if (ws.mRebuilding) {
7426                    StringWriter sw = new StringWriter();
7427                    PrintWriter pw = new PrintWriter(sw);
7428                    ws.dump(pw, "", true);
7429                    pw.flush();
7430                    Slog.w(TAG, "This window was lost: " + ws);
7431                    Slog.w(TAG, sw.toString());
7432                    ws.mWinAnimator.destroySurfaceLocked();
7433                }
7434            }
7435            Slog.w(TAG, "Current app token list:");
7436            dumpAppTokensLocked();
7437            Slog.w(TAG, "Final window list:");
7438            dumpWindowsLocked();
7439        }
7440    }
7441
7442    private final void assignLayersLocked(WindowList windows) {
7443        int N = windows.size();
7444        int curBaseLayer = 0;
7445        int curLayer = 0;
7446        int i;
7447
7448        if (DEBUG_LAYERS) {
7449            RuntimeException here = new RuntimeException("here");
7450            here.fillInStackTrace();
7451            Slog.v(TAG, "Assigning layers", here);
7452        }
7453
7454        boolean anyLayerChanged = false;
7455
7456        for (i=0; i<N; i++) {
7457            final WindowState w = windows.get(i);
7458            final WindowStateAnimator winAnimator = w.mWinAnimator;
7459            boolean layerChanged = false;
7460            int oldLayer = w.mLayer;
7461            if (w.mBaseLayer == curBaseLayer || w.mIsImWindow
7462                    || (i > 0 && w.mIsWallpaper)) {
7463                curLayer += WINDOW_LAYER_MULTIPLIER;
7464                w.mLayer = curLayer;
7465            } else {
7466                curBaseLayer = curLayer = w.mBaseLayer;
7467                w.mLayer = curLayer;
7468            }
7469            if (w.mLayer != oldLayer) {
7470                layerChanged = true;
7471                anyLayerChanged = true;
7472            }
7473            oldLayer = winAnimator.mAnimLayer;
7474            if (w.mTargetAppToken != null) {
7475                winAnimator.mAnimLayer =
7476                        w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment;
7477            } else if (w.mAppToken != null) {
7478                winAnimator.mAnimLayer =
7479                        w.mLayer + w.mAppToken.mAppAnimator.animLayerAdjustment;
7480            } else {
7481                winAnimator.mAnimLayer = w.mLayer;
7482            }
7483            if (w.mIsImWindow) {
7484                winAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment;
7485            } else if (w.mIsWallpaper) {
7486                winAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment;
7487            }
7488            if (winAnimator.mAnimLayer != oldLayer) {
7489                layerChanged = true;
7490                anyLayerChanged = true;
7491            }
7492            if (layerChanged && mAnimator.isDimmingLocked(winAnimator)) {
7493                // Force an animation pass just to update the mDimAnimator layer.
7494                scheduleAnimationLocked();
7495            }
7496            if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": "
7497                    + "mBase=" + w.mBaseLayer
7498                    + " mLayer=" + w.mLayer
7499                    + (w.mAppToken == null ?
7500                            "" : " mAppLayer=" + w.mAppToken.mAppAnimator.animLayerAdjustment)
7501                    + " =mAnimLayer=" + winAnimator.mAnimLayer);
7502            //System.out.println(
7503            //    "Assigned layer " + curLayer + " to " + w.mClient.asBinder());
7504        }
7505
7506        //TODO (multidisplay): Magnification is supported only for the default display.
7507        if (mDisplayMagnifier != null && anyLayerChanged
7508                && windows.get(windows.size() - 1).getDisplayId() == Display.DEFAULT_DISPLAY) {
7509            mDisplayMagnifier.onWindowLayersChangedLocked();
7510        }
7511    }
7512
7513    private final void performLayoutAndPlaceSurfacesLocked() {
7514        int loopCount = 6;
7515        do {
7516            mTraversalScheduled = false;
7517            performLayoutAndPlaceSurfacesLockedLoop();
7518            mH.removeMessages(H.DO_TRAVERSAL);
7519            loopCount--;
7520        } while (mTraversalScheduled && loopCount > 0);
7521        mInnerFields.mWallpaperActionPending = false;
7522    }
7523
7524    private boolean mInLayout = false;
7525    private final void performLayoutAndPlaceSurfacesLockedLoop() {
7526        if (mInLayout) {
7527            if (DEBUG) {
7528                throw new RuntimeException("Recursive call!");
7529            }
7530            Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers="
7531                    + Debug.getCallers(3));
7532            return;
7533        }
7534
7535        if (mWaitingForConfig) {
7536            // Our configuration has changed (most likely rotation), but we
7537            // don't yet have the complete configuration to report to
7538            // applications.  Don't do any window layout until we have it.
7539            return;
7540        }
7541
7542        if (!mDisplayReady) {
7543            // Not yet initialized, nothing to do.
7544            return;
7545        }
7546
7547        Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout");
7548        mInLayout = true;
7549        boolean recoveringMemory = false;
7550
7551        try {
7552            if (mForceRemoves != null) {
7553                recoveringMemory = true;
7554                // Wait a little bit for things to settle down, and off we go.
7555                for (int i=0; i<mForceRemoves.size(); i++) {
7556                    WindowState ws = mForceRemoves.get(i);
7557                    Slog.i(TAG, "Force removing: " + ws);
7558                    removeWindowInnerLocked(ws.mSession, ws);
7559                }
7560                mForceRemoves = null;
7561                Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");
7562                Object tmp = new Object();
7563                synchronized (tmp) {
7564                    try {
7565                        tmp.wait(250);
7566                    } catch (InterruptedException e) {
7567                    }
7568                }
7569            }
7570        } catch (RuntimeException e) {
7571            Log.wtf(TAG, "Unhandled exception while force removing for memory", e);
7572        }
7573
7574        try {
7575            performLayoutAndPlaceSurfacesLockedInner(recoveringMemory);
7576
7577            mInLayout = false;
7578
7579            if (needsLayout()) {
7580                if (++mLayoutRepeatCount < 6) {
7581                    requestTraversalLocked();
7582                } else {
7583                    Slog.e(TAG, "Performed 6 layouts in a row. Skipping");
7584                    mLayoutRepeatCount = 0;
7585                }
7586            } else {
7587                mLayoutRepeatCount = 0;
7588            }
7589
7590            if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) {
7591                mH.removeMessages(H.REPORT_WINDOWS_CHANGE);
7592                mH.sendEmptyMessage(H.REPORT_WINDOWS_CHANGE);
7593            }
7594        } catch (RuntimeException e) {
7595            mInLayout = false;
7596            Log.wtf(TAG, "Unhandled exception while laying out windows", e);
7597        }
7598
7599        Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
7600    }
7601
7602    private final void performLayoutLockedInner(final DisplayContent displayContent,
7603                                    boolean initial, boolean updateInputWindows) {
7604        if (!displayContent.layoutNeeded) {
7605            return;
7606        }
7607        displayContent.layoutNeeded = false;
7608        WindowList windows = displayContent.getWindowList();
7609        boolean isDefaultDisplay = displayContent.isDefaultDisplay;
7610
7611        DisplayInfo displayInfo = displayContent.getDisplayInfo();
7612        final int dw = displayInfo.logicalWidth;
7613        final int dh = displayInfo.logicalHeight;
7614
7615        final int NFW = mFakeWindows.size();
7616        for (int i=0; i<NFW; i++) {
7617            mFakeWindows.get(i).layout(dw, dh);
7618        }
7619
7620        final int N = windows.size();
7621        int i;
7622
7623        if (DEBUG_LAYOUT) {
7624            Slog.v(TAG, "-------------------------------------");
7625            Slog.v(TAG, "performLayout: needed="
7626                    + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh);
7627        }
7628
7629        WindowStateAnimator universeBackground = null;
7630
7631        mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mRotation);
7632        if (isDefaultDisplay) {
7633            // Not needed on non-default displays.
7634            mSystemDecorLayer = mPolicy.getSystemDecorRectLw(mSystemDecorRect);
7635            mScreenRect.set(0, 0, dw, dh);
7636        }
7637
7638        int seq = mLayoutSeq+1;
7639        if (seq < 0) seq = 0;
7640        mLayoutSeq = seq;
7641
7642        boolean behindDream = false;
7643
7644        // First perform layout of any root windows (not attached
7645        // to another window).
7646        int topAttached = -1;
7647        for (i = N-1; i >= 0; i--) {
7648            final WindowState win = windows.get(i);
7649
7650            // Don't do layout of a window if it is not visible, or
7651            // soon won't be visible, to avoid wasting time and funky
7652            // changes while a window is animating away.
7653            final boolean gone = (behindDream && mPolicy.canBeForceHidden(win, win.mAttrs))
7654                    || win.isGoneForLayoutLw();
7655
7656            if (DEBUG_LAYOUT && !win.mLayoutAttached) {
7657                Slog.v(TAG, "1ST PASS " + win
7658                        + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame
7659                        + " mLayoutAttached=" + win.mLayoutAttached
7660                        + " screen changed=" + win.isConfigChanged());
7661                final AppWindowToken atoken = win.mAppToken;
7662                if (gone) Slog.v(TAG, "  GONE: mViewVisibility="
7663                        + win.mViewVisibility + " mRelayoutCalled="
7664                        + win.mRelayoutCalled + " hidden="
7665                        + win.mRootToken.hidden + " hiddenRequested="
7666                        + (atoken != null && atoken.hiddenRequested)
7667                        + " mAttachedHidden=" + win.mAttachedHidden);
7668                else Slog.v(TAG, "  VIS: mViewVisibility="
7669                        + win.mViewVisibility + " mRelayoutCalled="
7670                        + win.mRelayoutCalled + " hidden="
7671                        + win.mRootToken.hidden + " hiddenRequested="
7672                        + (atoken != null && atoken.hiddenRequested)
7673                        + " mAttachedHidden=" + win.mAttachedHidden);
7674            }
7675
7676            // If this view is GONE, then skip it -- keep the current
7677            // frame, and let the caller know so they can ignore it
7678            // if they want.  (We do the normal layout for INVISIBLE
7679            // windows, since that means "perform layout as normal,
7680            // just don't display").
7681            if (!gone || !win.mHaveFrame || win.mLayoutNeeded
7682                    || (win.mAttrs.type == TYPE_KEYGUARD && win.isConfigChanged())
7683                    || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
7684                if (!win.mLayoutAttached) {
7685                    if (initial) {
7686                        //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
7687                        win.mContentChanged = false;
7688                    }
7689                    if (win.mAttrs.type == TYPE_DREAM) {
7690                        // Don't layout windows behind a dream, so that if it
7691                        // does stuff like hide the status bar we won't get a
7692                        // bad transition when it goes away.
7693                        behindDream = true;
7694                    }
7695                    win.mLayoutNeeded = false;
7696                    win.prelayout();
7697                    mPolicy.layoutWindowLw(win, win.mAttrs, null);
7698                    win.mLayoutSeq = seq;
7699                    if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame="
7700                            + win.mFrame + " mContainingFrame="
7701                            + win.mContainingFrame + " mDisplayFrame="
7702                            + win.mDisplayFrame);
7703                } else {
7704                    if (topAttached < 0) topAttached = i;
7705                }
7706            }
7707            if (win.mViewVisibility == View.VISIBLE
7708                    && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND
7709                    && universeBackground == null) {
7710                universeBackground = win.mWinAnimator;
7711            }
7712        }
7713
7714        if (mAnimator.mUniverseBackground  != universeBackground) {
7715            mFocusMayChange = true;
7716            mAnimator.mUniverseBackground = universeBackground;
7717        }
7718
7719        boolean attachedBehindDream = false;
7720
7721        // Now perform layout of attached windows, which usually
7722        // depend on the position of the window they are attached to.
7723        // XXX does not deal with windows that are attached to windows
7724        // that are themselves attached.
7725        for (i = topAttached; i >= 0; i--) {
7726            final WindowState win = windows.get(i);
7727
7728            if (win.mLayoutAttached) {
7729                if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win
7730                        + " mHaveFrame=" + win.mHaveFrame
7731                        + " mViewVisibility=" + win.mViewVisibility
7732                        + " mRelayoutCalled=" + win.mRelayoutCalled);
7733                // If this view is GONE, then skip it -- keep the current
7734                // frame, and let the caller know so they can ignore it
7735                // if they want.  (We do the normal layout for INVISIBLE
7736                // windows, since that means "perform layout as normal,
7737                // just don't display").
7738                if (attachedBehindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) {
7739                    continue;
7740                }
7741                if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled)
7742                        || !win.mHaveFrame || win.mLayoutNeeded) {
7743                    if (initial) {
7744                        //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
7745                        win.mContentChanged = false;
7746                    }
7747                    win.mLayoutNeeded = false;
7748                    win.prelayout();
7749                    mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow);
7750                    win.mLayoutSeq = seq;
7751                    if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame="
7752                            + win.mFrame + " mContainingFrame="
7753                            + win.mContainingFrame + " mDisplayFrame="
7754                            + win.mDisplayFrame);
7755                }
7756            } else if (win.mAttrs.type == TYPE_DREAM) {
7757                // Don't layout windows behind a dream, so that if it
7758                // does stuff like hide the status bar we won't get a
7759                // bad transition when it goes away.
7760                attachedBehindDream = behindDream;
7761            }
7762        }
7763
7764        // Window frames may have changed.  Tell the input dispatcher about it.
7765        mInputMonitor.setUpdateInputWindowsNeededLw();
7766        if (updateInputWindows) {
7767            mInputMonitor.updateInputWindowsLw(false /*force*/);
7768        }
7769
7770        mPolicy.finishLayoutLw();
7771    }
7772
7773    void makeWindowFreezingScreenIfNeededLocked(WindowState w) {
7774        // If the screen is currently frozen or off, then keep
7775        // it frozen/off until this window draws at its new
7776        // orientation.
7777        if (!okToDisplay()) {
7778            if (DEBUG_ORIENTATION) Slog.v(TAG,
7779                    "Changing surface while display frozen: " + w);
7780            w.mOrientationChanging = true;
7781            mInnerFields.mOrientationChangeComplete = false;
7782            if (!mWindowsFreezingScreen) {
7783                mWindowsFreezingScreen = true;
7784                // XXX should probably keep timeout from
7785                // when we first froze the display.
7786                mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
7787                mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT,
7788                        WINDOW_FREEZE_TIMEOUT_DURATION);
7789            }
7790        }
7791    }
7792
7793    /**
7794     * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
7795     * @param windows List of windows on default display.
7796     * @return bitmap indicating if another pass through layout must be made.
7797     */
7798    public int handleAppTransitionReadyLocked(WindowList windows) {
7799        int changes = 0;
7800        int i;
7801        int NN = mOpeningApps.size();
7802        boolean goodToGo = true;
7803        if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
7804                "Checking " + NN + " opening apps (frozen="
7805                + mDisplayFrozen + " timeout="
7806                + mAppTransition.isTimeout() + ")...");
7807        if (!mDisplayFrozen && !mAppTransition.isTimeout()) {
7808            // If the display isn't frozen, wait to do anything until
7809            // all of the apps are ready.  Otherwise just go because
7810            // we'll unfreeze the display when everyone is ready.
7811            for (i=0; i<NN && goodToGo; i++) {
7812                AppWindowToken wtoken = mOpeningApps.get(i);
7813                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
7814                        "Check opening app=" + wtoken + ": allDrawn="
7815                        + wtoken.allDrawn + " startingDisplayed="
7816                        + wtoken.startingDisplayed + " startingMoved="
7817                        + wtoken.startingMoved);
7818                if (!wtoken.allDrawn && !wtoken.startingDisplayed
7819                        && !wtoken.startingMoved) {
7820                    goodToGo = false;
7821                }
7822            }
7823        }
7824        if (goodToGo) {
7825            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO");
7826            int transit = mAppTransition.getAppTransition();
7827            if (mSkipAppTransitionAnimation) {
7828                transit = AppTransition.TRANSIT_UNSET;
7829            }
7830            mAppTransition.goodToGo();
7831            mStartingIconInTransition = false;
7832            mSkipAppTransitionAnimation = false;
7833
7834            mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
7835
7836            rebuildAppWindowListLocked();
7837
7838            // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper
7839            WindowState oldWallpaper =
7840                    mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating()
7841                        && !mWallpaperTarget.mWinAnimator.isDummyAnimation()
7842                    ? null : mWallpaperTarget;
7843
7844            mInnerFields.mWallpaperMayChange = false;
7845
7846            // The top-most window will supply the layout params,
7847            // and we will determine it below.
7848            LayoutParams animLp = null;
7849            int bestAnimLayer = -1;
7850            boolean fullscreenAnim = false;
7851
7852            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
7853                    "New wallpaper target=" + mWallpaperTarget
7854                    + ", oldWallpaper=" + oldWallpaper
7855                    + ", lower target=" + mLowerWallpaperTarget
7856                    + ", upper target=" + mUpperWallpaperTarget);
7857
7858            boolean openingAppHasWallpaper = false;
7859            boolean closingAppHasWallpaper = false;
7860            final AppWindowToken lowerWallpaperAppToken;
7861            final AppWindowToken upperWallpaperAppToken;
7862            if (mLowerWallpaperTarget == null) {
7863                lowerWallpaperAppToken = upperWallpaperAppToken = null;
7864            } else {
7865                lowerWallpaperAppToken = mLowerWallpaperTarget.mAppToken;
7866                upperWallpaperAppToken = mUpperWallpaperTarget.mAppToken;
7867            }
7868
7869            // Do a first pass through the tokens for two
7870            // things:
7871            // (1) Determine if both the closing and opening
7872            // app token sets are wallpaper targets, in which
7873            // case special animations are needed
7874            // (since the wallpaper needs to stay static
7875            // behind them).
7876            // (2) Find the layout params of the top-most
7877            // application window in the tokens, which is
7878            // what will control the animation theme.
7879            final int NC = mClosingApps.size();
7880            NN = NC + mOpeningApps.size();
7881            for (i=0; i<NN; i++) {
7882                final AppWindowToken wtoken;
7883                if (i < NC) {
7884                    wtoken = mClosingApps.get(i);
7885                    if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
7886                        closingAppHasWallpaper = true;
7887                    }
7888                } else {
7889                    wtoken = mOpeningApps.get(i - NC);
7890                    if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
7891                        openingAppHasWallpaper = true;
7892                    }
7893                }
7894
7895                if (wtoken.appFullscreen) {
7896                    WindowState ws = wtoken.findMainWindow();
7897                    if (ws != null) {
7898                        animLp = ws.mAttrs;
7899                        bestAnimLayer = ws.mLayer;
7900                        fullscreenAnim = true;
7901                    }
7902                } else if (!fullscreenAnim) {
7903                    WindowState ws = wtoken.findMainWindow();
7904                    if (ws != null) {
7905                        if (ws.mLayer > bestAnimLayer) {
7906                            animLp = ws.mAttrs;
7907                            bestAnimLayer = ws.mLayer;
7908                        }
7909                    }
7910                }
7911            }
7912
7913            if (closingAppHasWallpaper && openingAppHasWallpaper) {
7914                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!");
7915                switch (transit) {
7916                    case AppTransition.TRANSIT_ACTIVITY_OPEN:
7917                    case AppTransition.TRANSIT_TASK_OPEN:
7918                    case AppTransition.TRANSIT_TASK_TO_FRONT:
7919                        transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN;
7920                        break;
7921                    case AppTransition.TRANSIT_ACTIVITY_CLOSE:
7922                    case AppTransition.TRANSIT_TASK_CLOSE:
7923                    case AppTransition.TRANSIT_TASK_TO_BACK:
7924                        transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE;
7925                        break;
7926                }
7927                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit: " + transit);
7928            } else if ((oldWallpaper != null) && !mOpeningApps.contains(oldWallpaper.mAppToken)) {
7929                // We are transitioning from an activity with
7930                // a wallpaper to one without.
7931                transit = AppTransition.TRANSIT_WALLPAPER_CLOSE;
7932                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
7933                        "New transit away from wallpaper: " + transit);
7934            } else if (mWallpaperTarget != null && mWallpaperTarget.isVisibleLw()) {
7935                // We are transitioning from an activity without
7936                // a wallpaper to now showing the wallpaper
7937                transit = AppTransition.TRANSIT_WALLPAPER_OPEN;
7938                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
7939                        "New transit into wallpaper: " + transit);
7940            }
7941
7942            // If all closing windows are obscured, then there is
7943            // no need to do an animation.  This is the case, for
7944            // example, when this transition is being done behind
7945            // the lock screen.
7946            if (!mPolicy.allowAppAnimationsLw()) {
7947                animLp = null;
7948            }
7949
7950            AppWindowToken topOpeningApp = null;
7951            int topOpeningLayer = 0;
7952
7953            NN = mOpeningApps.size();
7954            for (i=0; i<NN; i++) {
7955                AppWindowToken wtoken = mOpeningApps.get(i);
7956                final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
7957                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken);
7958                appAnimator.clearThumbnail();
7959                wtoken.inPendingTransaction = false;
7960                appAnimator.animation = null;
7961                setTokenVisibilityLocked(wtoken, animLp, true, transit, false);
7962                wtoken.updateReportedVisibilityLocked();
7963                wtoken.waitingToShow = false;
7964
7965                appAnimator.mAllAppWinAnimators.clear();
7966                final int N = wtoken.allAppWindows.size();
7967                for (int j = 0; j < N; j++) {
7968                    appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
7969                }
7970                mAnimator.mAnimating |= appAnimator.showAllWindowsLocked();
7971
7972                if (animLp != null) {
7973                    int layer = -1;
7974                    for (int j=0; j<wtoken.windows.size(); j++) {
7975                        WindowState win = wtoken.windows.get(j);
7976                        if (win.mWinAnimator.mAnimLayer > layer) {
7977                            layer = win.mWinAnimator.mAnimLayer;
7978                        }
7979                    }
7980                    if (topOpeningApp == null || layer > topOpeningLayer) {
7981                        topOpeningApp = wtoken;
7982                        topOpeningLayer = layer;
7983                    }
7984                }
7985            }
7986            NN = mClosingApps.size();
7987            for (i=0; i<NN; i++) {
7988                AppWindowToken wtoken = mClosingApps.get(i);
7989                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
7990                        "Now closing app " + wtoken);
7991                wtoken.mAppAnimator.clearThumbnail();
7992                wtoken.inPendingTransaction = false;
7993                wtoken.mAppAnimator.animation = null;
7994                setTokenVisibilityLocked(wtoken, animLp, false,
7995                        transit, false);
7996                wtoken.updateReportedVisibilityLocked();
7997                wtoken.waitingToHide = false;
7998                // Force the allDrawn flag, because we want to start
7999                // this guy's animations regardless of whether it's
8000                // gotten drawn.
8001                wtoken.allDrawn = true;
8002                wtoken.deferClearAllDrawn = false;
8003            }
8004
8005            AppWindowAnimator appAnimator =
8006                    topOpeningApp == null ? null : topOpeningApp.mAppAnimator;
8007            Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail();
8008            if (nextAppTransitionThumbnail != null && appAnimator != null
8009                    && appAnimator.animation != null) {
8010                // This thumbnail animation is very special, we need to have
8011                // an extra surface with the thumbnail included with the animation.
8012                Rect dirty = new Rect(0, 0, nextAppTransitionThumbnail.getWidth(),
8013                        nextAppTransitionThumbnail.getHeight());
8014                try {
8015                    // TODO(multi-display): support other displays
8016                    final DisplayContent displayContent = getDefaultDisplayContentLocked();
8017                    final Display display = displayContent.getDisplay();
8018                    SurfaceControl surfaceControl = new SurfaceControl(mFxSession,
8019                            "thumbnail anim",
8020                            dirty.width(), dirty.height(),
8021                            PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
8022                    surfaceControl.setLayerStack(display.getLayerStack());
8023                    appAnimator.thumbnail = surfaceControl;
8024                    if (SHOW_TRANSACTIONS) Slog.i(TAG, "  THUMBNAIL " + surfaceControl + ": CREATE");
8025                    Surface drawSurface = new Surface();
8026                    drawSurface.copyFrom(surfaceControl);
8027                    Canvas c = drawSurface.lockCanvas(dirty);
8028                    c.drawBitmap(nextAppTransitionThumbnail, 0, 0, null);
8029                    drawSurface.unlockCanvasAndPost(c);
8030                    drawSurface.release();
8031                    appAnimator.thumbnailLayer = topOpeningLayer;
8032                    DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
8033                    Animation anim = mAppTransition.createThumbnailAnimationLocked(
8034                            transit, true, true, displayInfo.appWidth, displayInfo.appHeight);
8035                    appAnimator.thumbnailAnimation = anim;
8036                    anim.restrictDuration(MAX_ANIMATION_DURATION);
8037                    anim.scaleCurrentDuration(mTransitionAnimationScale);
8038                    Point p = new Point();
8039                    mAppTransition.getStartingPoint(p);
8040                    appAnimator.thumbnailX = p.x;
8041                    appAnimator.thumbnailY = p.y;
8042                } catch (SurfaceControl.OutOfResourcesException e) {
8043                    Slog.e(TAG, "Can't allocate thumbnail surface w=" + dirty.width()
8044                            + " h=" + dirty.height(), e);
8045                    appAnimator.clearThumbnail();
8046                } catch (Surface.OutOfResourcesException e) {
8047                    Slog.e(TAG, "Can't allocate Canvas surface w=" + dirty.width()
8048                            + " h=" + dirty.height(), e);
8049                    appAnimator.clearThumbnail();
8050                }
8051            }
8052
8053            mAppTransition.postAnimationCallback();
8054            mAppTransition.clear();
8055
8056            mOpeningApps.clear();
8057            mClosingApps.clear();
8058
8059            // This has changed the visibility of windows, so perform
8060            // a new layout to get them all up-to-date.
8061            changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT
8062                    | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
8063            getDefaultDisplayContentLocked().layoutNeeded = true;
8064
8065            // TODO(multidisplay): IMEs are only supported on the default display.
8066            if (windows == getDefaultWindowListLocked()
8067                    && !moveInputMethodWindowsIfNeededLocked(true)) {
8068                assignLayersLocked(windows);
8069            }
8070            updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, false /*updateInputWindows*/);
8071            mFocusMayChange = false;
8072        }
8073
8074        return changes;
8075    }
8076
8077    /**
8078     * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
8079     * @return bitmap indicating if another pass through layout must be made.
8080     */
8081    private int handleAnimatingStoppedAndTransitionLocked() {
8082        int changes = 0;
8083
8084        mAppTransition.setIdle();
8085        // Restore window app tokens to the ActivityManager views
8086        final DisplayContent displayContent = getDefaultDisplayContentLocked();
8087        AppTokenIterator iterator = displayContent.getTmpAppIterator(FORWARD_ITERATOR);
8088        while (iterator.hasNext()) {
8089            iterator.next().sendingToBottom = false;
8090        }
8091        rebuildAppWindowListLocked();
8092
8093        changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
8094        if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
8095                "Wallpaper layer changed: assigning layers + relayout");
8096        moveInputMethodWindowsIfNeededLocked(true);
8097        mInnerFields.mWallpaperMayChange = true;
8098        // Since the window list has been rebuilt, focus might
8099        // have to be recomputed since the actual order of windows
8100        // might have changed again.
8101        mFocusMayChange = true;
8102
8103        return changes;
8104    }
8105
8106    private void updateResizingWindows(final WindowState w) {
8107        final WindowStateAnimator winAnimator = w.mWinAnimator;
8108        if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq) {
8109            w.mContentInsetsChanged |=
8110                    !w.mLastContentInsets.equals(w.mContentInsets);
8111            w.mVisibleInsetsChanged |=
8112                    !w.mLastVisibleInsets.equals(w.mVisibleInsets);
8113            boolean configChanged = w.isConfigChanged();
8114            if (DEBUG_CONFIGURATION && configChanged) {
8115                Slog.v(TAG, "Win " + w + " config changed: "
8116                        + mCurConfiguration);
8117            }
8118            if (localLOGV) Slog.v(TAG, "Resizing " + w
8119                    + ": configChanged=" + configChanged
8120                    + " last=" + w.mLastFrame + " frame=" + w.mFrame);
8121            w.mLastFrame.set(w.mFrame);
8122            if (w.mContentInsetsChanged
8123                    || w.mVisibleInsetsChanged
8124                    || winAnimator.mSurfaceResized
8125                    || configChanged) {
8126                if (DEBUG_RESIZE || DEBUG_ORIENTATION) {
8127                    Slog.v(TAG, "Resize reasons: "
8128                            + " contentInsetsChanged=" + w.mContentInsetsChanged
8129                            + " " + w.mContentInsets.toShortString()
8130                            + " visibleInsetsChanged=" + w.mVisibleInsetsChanged
8131                            + " " + w.mVisibleInsets.toShortString()
8132                            + " surfaceResized=" + winAnimator.mSurfaceResized
8133                            + " configChanged=" + configChanged);
8134                }
8135
8136                w.mLastContentInsets.set(w.mContentInsets);
8137                w.mLastVisibleInsets.set(w.mVisibleInsets);
8138                makeWindowFreezingScreenIfNeededLocked(w);
8139                // If the orientation is changing, then we need to
8140                // hold off on unfreezing the display until this
8141                // window has been redrawn; to do that, we need
8142                // to go through the process of getting informed
8143                // by the application when it has finished drawing.
8144                if (w.mOrientationChanging) {
8145                    if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION) Slog.v(TAG,
8146                            "Orientation start waiting for draw mDrawState=DRAW_PENDING in "
8147                            + w + ", surface " + winAnimator.mSurfaceControl);
8148                    winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
8149                    if (w.mAppToken != null) {
8150                        w.mAppToken.allDrawn = false;
8151                        w.mAppToken.deferClearAllDrawn = false;
8152                    }
8153                }
8154                if (!mResizingWindows.contains(w)) {
8155                    if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
8156                            "Resizing window " + w + " to " + winAnimator.mSurfaceW
8157                            + "x" + winAnimator.mSurfaceH);
8158                    mResizingWindows.add(w);
8159                }
8160            } else if (w.mOrientationChanging) {
8161                if (w.isDrawnLw()) {
8162                    if (DEBUG_ORIENTATION) Slog.v(TAG,
8163                            "Orientation not waiting for draw in "
8164                            + w + ", surface " + winAnimator.mSurfaceControl);
8165                    w.mOrientationChanging = false;
8166                }
8167            }
8168        }
8169    }
8170
8171    /**
8172     * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
8173     *
8174     * @param w WindowState this method is applied to.
8175     * @param currentTime The time which animations use for calculating transitions.
8176     * @param innerDw Width of app window.
8177     * @param innerDh Height of app window.
8178     */
8179    private void handleNotObscuredLocked(final WindowState w, final long currentTime,
8180                                         final int innerDw, final int innerDh) {
8181        final WindowManager.LayoutParams attrs = w.mAttrs;
8182        final int attrFlags = attrs.flags;
8183        final boolean canBeSeen = w.isDisplayedLw();
8184
8185        if (w.mHasSurface) {
8186            if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) {
8187                mInnerFields.mHoldScreen = w.mSession;
8188            }
8189            if (!mInnerFields.mSyswin && w.mAttrs.screenBrightness >= 0
8190                    && mInnerFields.mScreenBrightness < 0) {
8191                mInnerFields.mScreenBrightness = w.mAttrs.screenBrightness;
8192            }
8193            if (!mInnerFields.mSyswin && w.mAttrs.buttonBrightness >= 0
8194                    && mInnerFields.mButtonBrightness < 0) {
8195                mInnerFields.mButtonBrightness = w.mAttrs.buttonBrightness;
8196            }
8197            if (!mInnerFields.mSyswin && w.mAttrs.userActivityTimeout >= 0
8198                    && mInnerFields.mUserActivityTimeout < 0) {
8199                mInnerFields.mUserActivityTimeout = w.mAttrs.userActivityTimeout;
8200            }
8201
8202            final int type = attrs.type;
8203            if (canBeSeen
8204                    && (type == TYPE_SYSTEM_DIALOG
8205                     || type == TYPE_RECENTS_OVERLAY
8206                     || type == TYPE_KEYGUARD
8207                     || type == TYPE_SYSTEM_ERROR)) {
8208                mInnerFields.mSyswin = true;
8209            }
8210
8211            if (canBeSeen) {
8212                if (type == TYPE_DREAM || type == TYPE_KEYGUARD) {
8213                    mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_MIRROR;
8214                } else if (mInnerFields.mDisplayHasContent
8215                        == LayoutFields.DISPLAY_CONTENT_UNKNOWN) {
8216                    mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_UNIQUE;
8217                }
8218            }
8219        }
8220
8221        boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn();
8222        if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) {
8223            // This window completely covers everything behind it,
8224            // so we want to leave all of them as undimmed (for
8225            // performance reasons).
8226            mInnerFields.mObscured = true;
8227        }
8228    }
8229
8230    private void handleFlagDimBehind(WindowState w, int innerDw, int innerDh) {
8231        final WindowManager.LayoutParams attrs = w.mAttrs;
8232        if ((attrs.flags & FLAG_DIM_BEHIND) != 0
8233                && w.isDisplayedLw()
8234                && !w.mExiting) {
8235            mInnerFields.mDimming = true;
8236            final WindowStateAnimator winAnimator = w.mWinAnimator;
8237            if (!mAnimator.isDimmingLocked(winAnimator)) {
8238                if (localLOGV) Slog.v(TAG, "Win " + w + " start dimming.");
8239                startDimmingLocked(winAnimator, w.mExiting ? 0 : w.mAttrs.dimAmount);
8240            }
8241        }
8242    }
8243
8244    private void updateAllDrawnLocked(DisplayContent displayContent) {
8245        // See if any windows have been drawn, so they (and others
8246        // associated with them) can now be shown.
8247        AppTokenIterator iterator = displayContent.getTmpAppIterator(FORWARD_ITERATOR);
8248        while (iterator.hasNext()) {
8249            AppWindowToken wtoken = iterator.next();
8250            if (!wtoken.allDrawn) {
8251                int numInteresting = wtoken.numInterestingWindows;
8252                if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
8253                    if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
8254                            "allDrawn: " + wtoken
8255                            + " interesting=" + numInteresting
8256                            + " drawn=" + wtoken.numDrawnWindows);
8257                    wtoken.allDrawn = true;
8258                }
8259            }
8260        }
8261    }
8262
8263    // "Something has changed!  Let's make it correct now."
8264    private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) {
8265        if (DEBUG_WINDOW_TRACE) {
8266            Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by "
8267                    + Debug.getCallers(3));
8268        }
8269
8270        final long currentTime = SystemClock.uptimeMillis();
8271
8272        int i;
8273
8274        if (mFocusMayChange) {
8275            mFocusMayChange = false;
8276            updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
8277                    false /*updateInputWindows*/);
8278        }
8279
8280        // Initialize state of exiting tokens.
8281        DisplayContentsIterator iterator = new DisplayContentsIterator();
8282        while (iterator.hasNext()) {
8283            final DisplayContent displayContent = iterator.next();
8284            for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) {
8285                displayContent.mExitingTokens.get(i).hasVisible = false;
8286            }
8287
8288            // Initialize state of exiting applications.
8289            for (i=displayContent.mExitingAppTokens.size()-1; i>=0; i--) {
8290                displayContent.mExitingAppTokens.get(i).hasVisible = false;
8291            }
8292        }
8293
8294        mInnerFields.mHoldScreen = null;
8295        mInnerFields.mScreenBrightness = -1;
8296        mInnerFields.mButtonBrightness = -1;
8297        mInnerFields.mUserActivityTimeout = -1;
8298        mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_UNKNOWN;
8299
8300        mTransactionSequence++;
8301
8302        final DisplayContent defaultDisplay = getDefaultDisplayContentLocked();
8303        final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo();
8304        final int defaultDw = defaultInfo.logicalWidth;
8305        final int defaultDh = defaultInfo.logicalHeight;
8306
8307        if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
8308                ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
8309        SurfaceControl.openTransaction();
8310        try {
8311
8312            if (mWatermark != null) {
8313                mWatermark.positionSurface(defaultDw, defaultDh);
8314            }
8315            if (mStrictModeFlash != null) {
8316                mStrictModeFlash.positionSurface(defaultDw, defaultDh);
8317            }
8318
8319            boolean focusDisplayed = false;
8320
8321            iterator = new DisplayContentsIterator();
8322            while (iterator.hasNext()) {
8323                boolean updateAllDrawn = false;
8324                final DisplayContent displayContent = iterator.next();
8325                WindowList windows = displayContent.getWindowList();
8326                DisplayInfo displayInfo = displayContent.getDisplayInfo();
8327                final int displayId = displayContent.getDisplayId();
8328                final int dw = displayInfo.logicalWidth;
8329                final int dh = displayInfo.logicalHeight;
8330                final int innerDw = displayInfo.appWidth;
8331                final int innerDh = displayInfo.appHeight;
8332                final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
8333
8334                // Reset for each display unless we are forcing mirroring.
8335                if (mInnerFields.mDisplayHasContent != LayoutFields.DISPLAY_CONTENT_MIRROR) {
8336                    mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_UNKNOWN;
8337                }
8338
8339                int repeats = 0;
8340                do {
8341                    repeats++;
8342                    if (repeats > 6) {
8343                        Slog.w(TAG, "Animation repeat aborted after too many iterations");
8344                        displayContent.layoutNeeded = false;
8345                        break;
8346                    }
8347
8348                    if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner",
8349                        displayContent.pendingLayoutChanges);
8350
8351                    if ((displayContent.pendingLayoutChanges &
8352                            WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0 &&
8353                            (adjustWallpaperWindowsLocked() &
8354                                    ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
8355                        assignLayersLocked(windows);
8356                        displayContent.layoutNeeded = true;
8357                    }
8358
8359                    if (isDefaultDisplay && (displayContent.pendingLayoutChanges
8360                            & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
8361                        if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
8362                        if (updateOrientationFromAppTokensLocked(true)) {
8363                            displayContent.layoutNeeded = true;
8364                            mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
8365                        }
8366                    }
8367
8368                    if ((displayContent.pendingLayoutChanges
8369                            & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
8370                        displayContent.layoutNeeded = true;
8371                    }
8372
8373                    // FIRST LOOP: Perform a layout, if needed.
8374                    if (repeats < 4) {
8375                        performLayoutLockedInner(displayContent, repeats == 1,
8376                                false /*updateInputWindows*/);
8377                    } else {
8378                        Slog.w(TAG, "Layout repeat skipped after too many iterations");
8379                    }
8380
8381                    // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think
8382                    // it is animating.
8383                    displayContent.pendingLayoutChanges = 0;
8384
8385                    if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number "
8386                            + mLayoutRepeatCount, displayContent.pendingLayoutChanges);
8387
8388                    if (isDefaultDisplay) {
8389                        mPolicy.beginPostLayoutPolicyLw(dw, dh);
8390                        for (i = windows.size() - 1; i >= 0; i--) {
8391                            WindowState w = windows.get(i);
8392                            if (w.mHasSurface) {
8393                                mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs);
8394                            }
8395                        }
8396                        displayContent.pendingLayoutChanges |= mPolicy.finishPostLayoutPolicyLw();
8397                        if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats(
8398                            "after finishPostLayoutPolicyLw", displayContent.pendingLayoutChanges);
8399                    }
8400                } while (displayContent.pendingLayoutChanges != 0);
8401
8402                mInnerFields.mObscured = false;
8403                mInnerFields.mDimming = false;
8404                mInnerFields.mSyswin = false;
8405
8406                // Only used if default window
8407                final boolean someoneLosingFocus = !mLosingFocus.isEmpty();
8408
8409                final int N = windows.size();
8410                for (i=N-1; i>=0; i--) {
8411                    WindowState w = windows.get(i);
8412
8413                    final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured;
8414
8415                    // Update effect.
8416                    w.mObscured = mInnerFields.mObscured;
8417                    if (!mInnerFields.mObscured) {
8418                        handleNotObscuredLocked(w, currentTime, innerDw, innerDh);
8419                    }
8420
8421                    if (!mInnerFields.mDimming) {
8422                        handleFlagDimBehind(w, innerDw, innerDh);
8423                    }
8424
8425                    if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w)
8426                            && w.isVisibleLw()) {
8427                        // This is the wallpaper target and its obscured state
8428                        // changed... make sure the current wallaper's visibility
8429                        // has been updated accordingly.
8430                        updateWallpaperVisibilityLocked();
8431                    }
8432
8433                    final WindowStateAnimator winAnimator = w.mWinAnimator;
8434
8435                    // If the window has moved due to its containing
8436                    // content frame changing, then we'd like to animate
8437                    // it.
8438                    if (w.mHasSurface && w.shouldAnimateMove()) {
8439                        // Frame has moved, containing content frame
8440                        // has also moved, and we're not currently animating...
8441                        // let's do something.
8442                        Animation a = AnimationUtils.loadAnimation(mContext,
8443                                com.android.internal.R.anim.window_move_from_decor);
8444                        winAnimator.setAnimation(a);
8445                        winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left;
8446                        winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top;
8447                        try {
8448                            w.mClient.moved(w.mFrame.left, w.mFrame.top);
8449                        } catch (RemoteException e) {
8450                        }
8451                    }
8452
8453                    //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
8454                    w.mContentChanged = false;
8455
8456                    // Moved from updateWindowsAndWallpaperLocked().
8457                    if (w.mHasSurface) {
8458                        // Take care of the window being ready to display.
8459                        final boolean committed =
8460                                winAnimator.commitFinishDrawingLocked(currentTime);
8461                        if (isDefaultDisplay && committed) {
8462                            if (w.mAttrs.type == TYPE_DREAM) {
8463                                // HACK: When a dream is shown, it may at that
8464                                // point hide the lock screen.  So we need to
8465                                // redo the layout to let the phone window manager
8466                                // make this happen.
8467                                displayContent.pendingLayoutChanges |=
8468                                        WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
8469                                if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
8470                                    debugLayoutRepeats(
8471                                        "dream and commitFinishDrawingLocked true",
8472                                        displayContent.pendingLayoutChanges);
8473                                }
8474                            }
8475                            if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
8476                                if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
8477                                        "First draw done in potential wallpaper target " + w);
8478                                mInnerFields.mWallpaperMayChange = true;
8479                                displayContent.pendingLayoutChanges |=
8480                                        WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
8481                                if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
8482                                    debugLayoutRepeats(
8483                                        "wallpaper and commitFinishDrawingLocked true",
8484                                        displayContent.pendingLayoutChanges);
8485                                }
8486                            }
8487                        }
8488
8489                        winAnimator.setSurfaceBoundariesLocked(recoveringMemory);
8490
8491                        final AppWindowToken atoken = w.mAppToken;
8492                        if (DEBUG_STARTING_WINDOW && atoken != null
8493                                && w == atoken.startingWindow) {
8494                            Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen="
8495                                + w.isOnScreen() + " allDrawn=" + atoken.allDrawn
8496                                + " freezingScreen=" + atoken.mAppAnimator.freezingScreen);
8497                        }
8498                        if (atoken != null
8499                                && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) {
8500                            if (atoken.lastTransactionSequence != mTransactionSequence) {
8501                                atoken.lastTransactionSequence = mTransactionSequence;
8502                                atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
8503                                atoken.startingDisplayed = false;
8504                            }
8505                            if ((w.isOnScreen() || winAnimator.mAttrType == TYPE_BASE_APPLICATION)
8506                                    && !w.mExiting && !w.mDestroying) {
8507                                if (WindowManagerService.DEBUG_VISIBILITY ||
8508                                        WindowManagerService.DEBUG_ORIENTATION) {
8509                                    Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
8510                                            + ", isAnimating=" + winAnimator.isAnimating());
8511                                    if (!w.isDrawnLw()) {
8512                                        Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceControl
8513                                                + " pv=" + w.mPolicyVisibility
8514                                                + " mDrawState=" + winAnimator.mDrawState
8515                                                + " ah=" + w.mAttachedHidden
8516                                                + " th=" + atoken.hiddenRequested
8517                                                + " a=" + winAnimator.mAnimating);
8518                                    }
8519                                }
8520                                if (w != atoken.startingWindow) {
8521                                    if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) {
8522                                        atoken.numInterestingWindows++;
8523                                        if (w.isDrawnLw()) {
8524                                            atoken.numDrawnWindows++;
8525                                            if (WindowManagerService.DEBUG_VISIBILITY ||
8526                                                    WindowManagerService.DEBUG_ORIENTATION) Slog.v(TAG,
8527                                                    "tokenMayBeDrawn: " + atoken
8528                                                    + " freezingScreen=" + atoken.mAppAnimator.freezingScreen
8529                                                    + " mAppFreezing=" + w.mAppFreezing);
8530                                            updateAllDrawn = true;
8531                                        }
8532                                    }
8533                                } else if (w.isDrawnLw()) {
8534                                    atoken.startingDisplayed = true;
8535                                }
8536                            }
8537                        }
8538                    }
8539
8540                    if (isDefaultDisplay && someoneLosingFocus && (w == mCurrentFocus)
8541                            && w.isDisplayedLw()) {
8542                        focusDisplayed = true;
8543                    }
8544
8545                    updateResizingWindows(w);
8546                }
8547
8548                final boolean hasUniqueContent;
8549                switch (mInnerFields.mDisplayHasContent) {
8550                    case LayoutFields.DISPLAY_CONTENT_MIRROR:
8551                        hasUniqueContent = isDefaultDisplay;
8552                        break;
8553                    case LayoutFields.DISPLAY_CONTENT_UNIQUE:
8554                        hasUniqueContent = true;
8555                        break;
8556                    case LayoutFields.DISPLAY_CONTENT_UNKNOWN:
8557                    default:
8558                        hasUniqueContent = false;
8559                        break;
8560                }
8561                mDisplayManagerService.setDisplayHasContent(displayId, hasUniqueContent,
8562                        true /* inTraversal, must call performTraversalInTrans... below */);
8563
8564                if (!mInnerFields.mDimming && mAnimator.isDimmingLocked(displayId)) {
8565                    stopDimmingLocked(displayId);
8566                }
8567
8568                if (updateAllDrawn) {
8569                    updateAllDrawnLocked(displayContent);
8570                }
8571            }
8572
8573            if (focusDisplayed) {
8574                mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS);
8575            }
8576
8577            // Give the display manager a chance to adjust properties
8578            // like display rotation if it needs to.
8579            mDisplayManagerService.performTraversalInTransactionFromWindowManager();
8580
8581        } catch (RuntimeException e) {
8582            Log.wtf(TAG, "Unhandled exception in Window Manager", e);
8583        } finally {
8584            SurfaceControl.closeTransaction();
8585            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
8586                    "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
8587        }
8588
8589        final WindowList defaultWindows = defaultDisplay.getWindowList();
8590
8591        // If we are ready to perform an app transition, check through
8592        // all of the app tokens to be shown and see if they are ready
8593        // to go.
8594        if (mAppTransition.isReady()) {
8595            defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows);
8596            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked",
8597                    defaultDisplay.pendingLayoutChanges);
8598        }
8599
8600        if (!mAnimator.mAnimating && mAppTransition.isRunning()) {
8601            // We have finished the animation of an app transition.  To do
8602            // this, we have delayed a lot of operations like showing and
8603            // hiding apps, moving apps in Z-order, etc.  The app token list
8604            // reflects the correct Z-order, but the window list may now
8605            // be out of sync with it.  So here we will just rebuild the
8606            // entire app window list.  Fun!
8607            defaultDisplay.pendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked();
8608            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock",
8609                defaultDisplay.pendingLayoutChanges);
8610        }
8611
8612        if (mInnerFields.mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0
8613                && !mAppTransition.isReady()) {
8614            // At this point, there was a window with a wallpaper that
8615            // was force hiding other windows behind it, but now it
8616            // is going away.  This may be simple -- just animate
8617            // away the wallpaper and its window -- or it may be
8618            // hard -- the wallpaper now needs to be shown behind
8619            // something that was hidden.
8620            defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
8621            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked",
8622                defaultDisplay.pendingLayoutChanges);
8623        }
8624        mInnerFields.mWallpaperForceHidingChanged = false;
8625
8626        if (mInnerFields.mWallpaperMayChange) {
8627            if (WindowManagerService.DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
8628                    "Wallpaper may change!  Adjusting");
8629            defaultDisplay.pendingLayoutChanges |=
8630                    WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
8631            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("WallpaperMayChange",
8632                    defaultDisplay.pendingLayoutChanges);
8633        }
8634
8635        if (mFocusMayChange) {
8636            mFocusMayChange = false;
8637            if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
8638                    false /*updateInputWindows*/)) {
8639                defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
8640            }
8641        }
8642
8643        if (needsLayout()) {
8644            defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
8645            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded",
8646                    defaultDisplay.pendingLayoutChanges);
8647        }
8648
8649        for (i = mResizingWindows.size() - 1; i >= 0; i--) {
8650            WindowState win = mResizingWindows.get(i);
8651            if (win.mAppFreezing) {
8652                // Don't remove this window until rotation has completed.
8653                continue;
8654            }
8655            final WindowStateAnimator winAnimator = win.mWinAnimator;
8656            try {
8657                if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
8658                        "Reporting new frame to " + win + ": " + win.mCompatFrame);
8659                int diff = 0;
8660                boolean configChanged = win.isConfigChanged();
8661                if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION)
8662                        && configChanged) {
8663                    Slog.i(TAG, "Sending new config to window " + win + ": "
8664                            + winAnimator.mSurfaceW + "x" + winAnimator.mSurfaceH
8665                            + " / " + mCurConfiguration + " / 0x"
8666                            + Integer.toHexString(diff));
8667                }
8668                win.setConfiguration(mCurConfiguration);
8669                if (DEBUG_ORIENTATION &&
8670                        winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING) Slog.i(
8671                        TAG, "Resizing " + win + " WITH DRAW PENDING");
8672                win.mClient.resized(win.mFrame, win.mLastContentInsets, win.mLastVisibleInsets,
8673                        winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING,
8674                        configChanged ? win.mConfiguration : null);
8675                win.mContentInsetsChanged = false;
8676                win.mVisibleInsetsChanged = false;
8677                winAnimator.mSurfaceResized = false;
8678            } catch (RemoteException e) {
8679                win.mOrientationChanging = false;
8680            }
8681            mResizingWindows.remove(i);
8682        }
8683
8684        if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG,
8685                "With display frozen, orientationChangeComplete="
8686                + mInnerFields.mOrientationChangeComplete);
8687        if (mInnerFields.mOrientationChangeComplete) {
8688            if (mWindowsFreezingScreen) {
8689                mWindowsFreezingScreen = false;
8690                mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
8691            }
8692            stopFreezingDisplayLocked();
8693        }
8694
8695        // Destroy the surface of any windows that are no longer visible.
8696        boolean wallpaperDestroyed = false;
8697        i = mDestroySurface.size();
8698        if (i > 0) {
8699            do {
8700                i--;
8701                WindowState win = mDestroySurface.get(i);
8702                win.mDestroying = false;
8703                if (mInputMethodWindow == win) {
8704                    mInputMethodWindow = null;
8705                }
8706                if (win == mWallpaperTarget) {
8707                    wallpaperDestroyed = true;
8708                }
8709                win.mWinAnimator.destroySurfaceLocked();
8710            } while (i > 0);
8711            mDestroySurface.clear();
8712        }
8713
8714        // Time to remove any exiting tokens?
8715        iterator = new DisplayContentsIterator();
8716        while (iterator.hasNext()) {
8717            final DisplayContent displayContent = iterator.next();
8718            ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens;
8719            for (i = exitingTokens.size() - 1; i >= 0; i--) {
8720                WindowToken token = exitingTokens.get(i);
8721                if (!token.hasVisible) {
8722                    exitingTokens.remove(i);
8723                    if (token.windowType == TYPE_WALLPAPER) {
8724                        mWallpaperTokens.remove(token);
8725                    }
8726                }
8727            }
8728
8729            // Time to remove any exiting applications?
8730            AppTokenList exitingAppTokens = displayContent.mExitingAppTokens;
8731            for (i = exitingAppTokens.size() - 1; i >= 0; i--) {
8732                AppWindowToken token = exitingAppTokens.get(i);
8733                if (!token.hasVisible && !mClosingApps.contains(token)) {
8734                    // Make sure there is no animation running on this token,
8735                    // so any windows associated with it will be removed as
8736                    // soon as their animations are complete
8737                    token.mAppAnimator.clearAnimation();
8738                    token.mAppAnimator.animating = false;
8739                    if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
8740                            "performLayout: App token exiting now removed" + token);
8741                    displayContent.removeAppToken(token);
8742                    exitingAppTokens.remove(i);
8743                }
8744            }
8745        }
8746
8747        if (!mAnimator.mAnimating && mRelayoutWhileAnimating.size() > 0) {
8748            for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) {
8749                try {
8750                    mRelayoutWhileAnimating.get(j).mClient.doneAnimating();
8751                } catch (RemoteException e) {
8752                }
8753            }
8754            mRelayoutWhileAnimating.clear();
8755        }
8756
8757        if (wallpaperDestroyed) {
8758            defaultDisplay.pendingLayoutChanges |=
8759                    WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
8760            defaultDisplay.layoutNeeded = true;
8761        }
8762
8763        iterator = new DisplayContentsIterator();
8764        while (iterator.hasNext()) {
8765            DisplayContent displayContent = iterator.next();
8766            if (displayContent.pendingLayoutChanges != 0) {
8767                displayContent.layoutNeeded = true;
8768            }
8769        }
8770
8771        // Finally update all input windows now that the window changes have stabilized.
8772        mInputMonitor.updateInputWindowsLw(true /*force*/);
8773
8774        setHoldScreenLocked(mInnerFields.mHoldScreen);
8775        if (!mDisplayFrozen) {
8776            if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) {
8777                mPowerManager.setScreenBrightnessOverrideFromWindowManager(-1);
8778            } else {
8779                mPowerManager.setScreenBrightnessOverrideFromWindowManager(
8780                        toBrightnessOverride(mInnerFields.mScreenBrightness));
8781            }
8782            if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) {
8783                mPowerManager.setButtonBrightnessOverrideFromWindowManager(-1);
8784            } else {
8785                mPowerManager.setButtonBrightnessOverrideFromWindowManager(
8786                        toBrightnessOverride(mInnerFields.mButtonBrightness));
8787            }
8788            mPowerManager.setUserActivityTimeoutOverrideFromWindowManager(
8789                    mInnerFields.mUserActivityTimeout);
8790        }
8791
8792        if (mTurnOnScreen) {
8793            if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!");
8794            mPowerManager.wakeUp(SystemClock.uptimeMillis());
8795            mTurnOnScreen = false;
8796        }
8797
8798        if (mInnerFields.mUpdateRotation) {
8799            if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
8800            if (updateRotationUncheckedLocked(false)) {
8801                mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
8802            } else {
8803                mInnerFields.mUpdateRotation = false;
8804            }
8805        }
8806
8807        if (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded
8808                && !mInnerFields.mUpdateRotation) {
8809            checkDrawnWindowsLocked();
8810        }
8811
8812        final int N = mPendingRemove.size();
8813        if (N > 0) {
8814            if (mPendingRemoveTmp.length < N) {
8815                mPendingRemoveTmp = new WindowState[N+10];
8816            }
8817            mPendingRemove.toArray(mPendingRemoveTmp);
8818            mPendingRemove.clear();
8819            DisplayContentList displayList = new DisplayContentList();
8820            for (i = 0; i < N; i++) {
8821                WindowState w = mPendingRemoveTmp[i];
8822                removeWindowInnerLocked(w.mSession, w);
8823                if (!displayList.contains(w.mDisplayContent)) {
8824                    displayList.add(w.mDisplayContent);
8825                }
8826            }
8827
8828            for (DisplayContent displayContent : displayList) {
8829                assignLayersLocked(displayContent.getWindowList());
8830                displayContent.layoutNeeded = true;
8831            }
8832        }
8833
8834        // Check to see if we are now in a state where the screen should
8835        // be enabled, because the window obscured flags have changed.
8836        enableScreenIfNeededLocked();
8837
8838        scheduleAnimationLocked();
8839
8840        if (DEBUG_WINDOW_TRACE) {
8841            Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: animating="
8842                    + mAnimator.mAnimating);
8843        }
8844    }
8845
8846    private int toBrightnessOverride(float value) {
8847        return (int)(value * PowerManager.BRIGHTNESS_ON);
8848    }
8849
8850    void checkDrawnWindowsLocked() {
8851        if (mWaitingForDrawn.size() > 0) {
8852            for (int j=mWaitingForDrawn.size()-1; j>=0; j--) {
8853                Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(j);
8854                WindowState win = pair.first;
8855                //Slog.i(TAG, "Waiting for drawn " + win + ": removed="
8856                //        + win.mRemoved + " visible=" + win.isVisibleLw()
8857                //        + " shown=" + win.mSurfaceShown);
8858                if (win.mRemoved || !win.isVisibleLw()) {
8859                    // Window has been removed or made invisible; no draw
8860                    // will now happen, so stop waiting.
8861                    Slog.w(TAG, "Aborted waiting for drawn: " + pair.first);
8862                    try {
8863                        pair.second.sendResult(null);
8864                    } catch (RemoteException e) {
8865                    }
8866                    mWaitingForDrawn.remove(pair);
8867                    mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
8868                } else if (win.mWinAnimator.mSurfaceShown) {
8869                    // Window is now drawn (and shown).
8870                    try {
8871                        pair.second.sendResult(null);
8872                    } catch (RemoteException e) {
8873                    }
8874                    mWaitingForDrawn.remove(pair);
8875                    mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
8876                }
8877            }
8878        }
8879    }
8880
8881    @Override
8882    public boolean waitForWindowDrawn(IBinder token, IRemoteCallback callback) {
8883        if (token != null && callback != null) {
8884            synchronized (mWindowMap) {
8885                WindowState win = windowForClientLocked(null, token, true);
8886                if (win != null) {
8887                    Pair<WindowState, IRemoteCallback> pair =
8888                            new Pair<WindowState, IRemoteCallback>(win, callback);
8889                    Message m = mH.obtainMessage(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
8890                    mH.sendMessageDelayed(m, 2000);
8891                    mWaitingForDrawn.add(pair);
8892                    checkDrawnWindowsLocked();
8893                    return true;
8894                }
8895            }
8896        }
8897        return false;
8898    }
8899
8900    void setHoldScreenLocked(final Session newHoldScreen) {
8901        final boolean hold = newHoldScreen != null;
8902
8903        if (hold && mHoldingScreenOn != newHoldScreen) {
8904            mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid));
8905        }
8906        mHoldingScreenOn = newHoldScreen;
8907
8908        final boolean state = mHoldingScreenWakeLock.isHeld();
8909        if (hold != state) {
8910            if (hold) {
8911                mHoldingScreenWakeLock.acquire();
8912                mPolicy.keepScreenOnStartedLw();
8913            } else {
8914                mPolicy.keepScreenOnStoppedLw();
8915                mHoldingScreenWakeLock.release();
8916            }
8917        }
8918    }
8919
8920    @Override
8921    public void requestTraversal() {
8922        synchronized (mWindowMap) {
8923            requestTraversalLocked();
8924        }
8925    }
8926
8927    void requestTraversalLocked() {
8928        if (!mTraversalScheduled) {
8929            mTraversalScheduled = true;
8930            mH.sendEmptyMessage(H.DO_TRAVERSAL);
8931        }
8932    }
8933
8934    /** Note that Locked in this case is on mLayoutToAnim */
8935    void scheduleAnimationLocked() {
8936        if (!mAnimationScheduled) {
8937            mAnimationScheduled = true;
8938            mChoreographer.postCallback(
8939                    Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null);
8940        }
8941    }
8942
8943    void startDimmingLocked(final WindowStateAnimator winAnimator, final float target) {
8944        mAnimator.setDimWinAnimatorLocked(winAnimator.mWin.getDisplayId(), winAnimator);
8945    }
8946
8947    void stopDimmingLocked(int displayId) {
8948        mAnimator.setDimWinAnimatorLocked(displayId, null);
8949    }
8950
8951    private boolean needsLayout() {
8952        DisplayContentsIterator iterator = new DisplayContentsIterator();
8953        while (iterator.hasNext()) {
8954            if (iterator.next().layoutNeeded) {
8955                return true;
8956            }
8957        }
8958        return false;
8959    }
8960
8961    boolean copyAnimToLayoutParamsLocked() {
8962        boolean doRequest = false;
8963
8964        final int bulkUpdateParams = mAnimator.mBulkUpdateParams;
8965        if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) {
8966            mInnerFields.mUpdateRotation = true;
8967            doRequest = true;
8968        }
8969        if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) {
8970            mInnerFields.mWallpaperMayChange = true;
8971            doRequest = true;
8972        }
8973        if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) {
8974            mInnerFields.mWallpaperForceHidingChanged = true;
8975            doRequest = true;
8976        }
8977        if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) == 0) {
8978            mInnerFields.mOrientationChangeComplete = false;
8979        } else {
8980            mInnerFields.mOrientationChangeComplete = true;
8981            if (mWindowsFreezingScreen) {
8982                doRequest = true;
8983            }
8984        }
8985        if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) {
8986            mTurnOnScreen = true;
8987        }
8988        if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_ACTION_PENDING) != 0) {
8989            mInnerFields.mWallpaperActionPending = true;
8990        }
8991
8992        return doRequest;
8993    }
8994
8995    boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation,
8996                                           boolean secure) {
8997        final SurfaceControl surface = winAnimator.mSurfaceControl;
8998        boolean leakedSurface = false;
8999        boolean killedApps = false;
9000
9001        EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(),
9002                winAnimator.mSession.mPid, operation);
9003
9004        if (mForceRemoves == null) {
9005            mForceRemoves = new ArrayList<WindowState>();
9006        }
9007
9008        long callingIdentity = Binder.clearCallingIdentity();
9009        try {
9010            // There was some problem...   first, do a sanity check of the
9011            // window list to make sure we haven't left any dangling surfaces
9012            // around.
9013
9014            mTmpWindowsIterator.reset(FORWARD_ITERATOR);
9015            Slog.i(TAG, "Out of memory for surface!  Looking for leaks...");
9016            while (mTmpWindowsIterator.hasNext()) {
9017                WindowState ws = mTmpWindowsIterator.next();
9018                WindowStateAnimator wsa = ws.mWinAnimator;
9019                if (wsa.mSurfaceControl != null) {
9020                    if (!mSessions.contains(wsa.mSession)) {
9021                        Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): "
9022                                + ws + " surface=" + wsa.mSurfaceControl
9023                                + " token=" + ws.mToken
9024                                + " pid=" + ws.mSession.mPid
9025                                + " uid=" + ws.mSession.mUid);
9026                        if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null);
9027                        wsa.mSurfaceControl.destroy();
9028                        wsa.mSurfaceShown = false;
9029                        wsa.mSurfaceControl = null;
9030                        ws.mHasSurface = false;
9031                        mForceRemoves.add(ws);
9032                        leakedSurface = true;
9033                    } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) {
9034                        Slog.w(TAG, "LEAKED SURFACE (app token hidden): "
9035                                + ws + " surface=" + wsa.mSurfaceControl
9036                                + " token=" + ws.mAppToken);
9037                        if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null);
9038                        wsa.mSurfaceControl.destroy();
9039                        wsa.mSurfaceShown = false;
9040                        wsa.mSurfaceControl = null;
9041                        ws.mHasSurface = false;
9042                        leakedSurface = true;
9043                    }
9044                }
9045            }
9046
9047            if (!leakedSurface) {
9048                Slog.w(TAG, "No leaked surfaces; killing applicatons!");
9049                SparseIntArray pidCandidates = new SparseIntArray();
9050                mTmpWindowsIterator.reset(FORWARD_ITERATOR);
9051                while (mTmpWindowsIterator.hasNext()) {
9052                    WindowState ws = mTmpWindowsIterator.next();
9053                    if (mForceRemoves.contains(ws)) {
9054                        continue;
9055                    }
9056                    WindowStateAnimator wsa = ws.mWinAnimator;
9057                    if (wsa.mSurfaceControl != null) {
9058                        pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid);
9059                    }
9060                }
9061                if (pidCandidates.size() > 0) {
9062                    int[] pids = new int[pidCandidates.size()];
9063                    for (int i=0; i<pids.length; i++) {
9064                        pids[i] = pidCandidates.keyAt(i);
9065                    }
9066                    try {
9067                        if (mActivityManager.killPids(pids, "Free memory", secure)) {
9068                            killedApps = true;
9069                        }
9070                    } catch (RemoteException e) {
9071                    }
9072                }
9073            }
9074
9075            if (leakedSurface || killedApps) {
9076                // We managed to reclaim some memory, so get rid of the trouble
9077                // surface and ask the app to request another one.
9078                Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry.");
9079                if (surface != null) {
9080                    if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin,
9081                            "RECOVER DESTROY", null);
9082                    surface.destroy();
9083                    winAnimator.mSurfaceShown = false;
9084                    winAnimator.mSurfaceControl = null;
9085                    winAnimator.mWin.mHasSurface = false;
9086                }
9087
9088                try {
9089                    winAnimator.mWin.mClient.dispatchGetNewSurface();
9090                } catch (RemoteException e) {
9091                }
9092            }
9093        } finally {
9094            Binder.restoreCallingIdentity(callingIdentity);
9095        }
9096
9097        return leakedSurface || killedApps;
9098    }
9099
9100    private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
9101        WindowState newFocus = computeFocusedWindowLocked();
9102        if (mCurrentFocus != newFocus) {
9103            Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus");
9104            // This check makes sure that we don't already have the focus
9105            // change message pending.
9106            mH.removeMessages(H.REPORT_FOCUS_CHANGE);
9107            mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
9108            if (localLOGV) Slog.v(
9109                TAG, "Changing focus from " + mCurrentFocus + " to " + newFocus);
9110            final WindowState oldFocus = mCurrentFocus;
9111            mCurrentFocus = newFocus;
9112            mAnimator.setCurrentFocus(newFocus);
9113            mLosingFocus.remove(newFocus);
9114            int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
9115
9116            // TODO(multidisplay): Focused windows on default display only.
9117            final DisplayContent displayContent = getDefaultDisplayContentLocked();
9118
9119            final WindowState imWindow = mInputMethodWindow;
9120            if (newFocus != imWindow && oldFocus != imWindow) {
9121                if (moveInputMethodWindowsIfNeededLocked(
9122                        mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS &&
9123                        mode != UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
9124                    displayContent.layoutNeeded = true;
9125                }
9126                if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
9127                    performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows);
9128                    focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9129                } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
9130                    // Client will do the layout, but we need to assign layers
9131                    // for handleNewWindowLocked() below.
9132                    assignLayersLocked(displayContent.getWindowList());
9133                }
9134            }
9135
9136            if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
9137                // The change in focus caused us to need to do a layout.  Okay.
9138                displayContent.layoutNeeded = true;
9139                if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
9140                    performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows);
9141                }
9142            }
9143
9144            if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
9145                // If we defer assigning layers, then the caller is responsible for
9146                // doing this part.
9147                finishUpdateFocusedWindowAfterAssignLayersLocked(updateInputWindows);
9148            }
9149
9150            Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
9151            return true;
9152        }
9153        return false;
9154    }
9155
9156    private void finishUpdateFocusedWindowAfterAssignLayersLocked(boolean updateInputWindows) {
9157        mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows);
9158    }
9159
9160    private WindowState computeFocusedWindowLocked() {
9161        if (mAnimator.mUniverseBackground != null
9162                && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) {
9163            return mAnimator.mUniverseBackground.mWin;
9164        }
9165
9166        final int displayCount = mDisplayContents.size();
9167        for (int i = 0; i < displayCount; i++) {
9168            final DisplayContent displayContent = mDisplayContents.valueAt(i);
9169            WindowState win = findFocusedWindowLocked(displayContent);
9170            if (win != null) {
9171                return win;
9172            }
9173        }
9174        return null;
9175    }
9176
9177    private WindowState findFocusedWindowLocked(DisplayContent displayContent) {
9178        AppTokenIterator iterator = displayContent.getTmpAppIterator(REVERSE_ITERATOR);
9179        WindowToken nextApp = iterator.hasNext() ? iterator.next() : null;
9180
9181        final WindowList windows = displayContent.getWindowList();
9182        for (int i = windows.size() - 1; i >= 0; i--) {
9183            final WindowState win = windows.get(i);
9184
9185            if (localLOGV || DEBUG_FOCUS) Slog.v(
9186                TAG, "Looking for focus: " + i
9187                + " = " + win
9188                + ", flags=" + win.mAttrs.flags
9189                + ", canReceive=" + win.canReceiveKeys());
9190
9191            AppWindowToken thisApp = win.mAppToken;
9192
9193            // If this window's application has been removed, just skip it.
9194            if (thisApp != null && (thisApp.removed || thisApp.sendingToBottom)) {
9195                if (DEBUG_FOCUS) Slog.v(TAG, "Skipping app because " + (thisApp.removed
9196                        ? "removed" : "sendingToBottom"));
9197                continue;
9198            }
9199
9200            // If there is a focused app, don't allow focus to go to any
9201            // windows below it.  If this is an application window, step
9202            // through the app tokens until we find its app.
9203            if (thisApp != null && nextApp != null && thisApp != nextApp
9204                    && win.mAttrs.type != TYPE_APPLICATION_STARTING) {
9205                final WindowToken origAppToken = nextApp;
9206                while (iterator.hasNext()) {
9207                    if (nextApp == mFocusedApp) {
9208                        // Whoops, we are below the focused app...  no focus
9209                        // for you!
9210                        if (localLOGV || DEBUG_FOCUS) Slog.v(
9211                            TAG, "Reached focused app: " + mFocusedApp);
9212                        return null;
9213                    }
9214                    nextApp = iterator.next();
9215                    if (nextApp == thisApp) {
9216                        break;
9217                    }
9218                }
9219                if (thisApp != nextApp) {
9220                    // Uh oh, the app token doesn't exist!  This shouldn't
9221                    // happen, but if it does we can get totally hosed...
9222                    // so restart at the original app.
9223                    nextApp = origAppToken;
9224                    iterator = displayContent.new AppTokenIterator(true);
9225                    while (iterator.hasNext()) {
9226                        // return iterator to same place.
9227                        if (iterator.next() == origAppToken) {
9228                            break;
9229                        }
9230                    }
9231                }
9232            }
9233
9234            // Dispatch to this window if it is wants key events.
9235            if (win.canReceiveKeys()) {
9236                if (DEBUG_FOCUS) Slog.v(
9237                        TAG, "Found focus @ " + i + " = " + win);
9238                return win;
9239            }
9240        }
9241        return null;
9242    }
9243
9244    private void startFreezingDisplayLocked(boolean inTransaction,
9245            int exitAnim, int enterAnim) {
9246        if (mDisplayFrozen) {
9247            return;
9248        }
9249
9250        if (!mDisplayReady || !mPolicy.isScreenOnFully()) {
9251            // No need to freeze the screen before the system is ready or if
9252            // the screen is off.
9253            return;
9254        }
9255
9256        mScreenFrozenLock.acquire();
9257
9258        mDisplayFrozen = true;
9259
9260        mInputMonitor.freezeInputDispatchingLw();
9261
9262        // Clear the last input window -- that is just used for
9263        // clean transitions between IMEs, and if we are freezing
9264        // the screen then the whole world is changing behind the scenes.
9265        mPolicy.setLastInputMethodWindowLw(null, null);
9266
9267        if (mAppTransition.isTransitionSet()) {
9268            mAppTransition.freeze();
9269        }
9270
9271        if (PROFILE_ORIENTATION) {
9272            File file = new File("/data/system/frozen");
9273            Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
9274        }
9275
9276        if (CUSTOM_SCREEN_ROTATION) {
9277            final DisplayContent displayContent = getDefaultDisplayContentLocked();
9278            final int displayId = displayContent.getDisplayId();
9279            ScreenRotationAnimation screenRotationAnimation =
9280                    mAnimator.getScreenRotationAnimationLocked(displayId);
9281            if (screenRotationAnimation != null) {
9282                screenRotationAnimation.kill();
9283            }
9284
9285            // TODO(multidisplay): rotation on main screen only.
9286            final Display display = displayContent.getDisplay();
9287            final DisplayInfo displayInfo = displayContent.getDisplayInfo();
9288            screenRotationAnimation = new ScreenRotationAnimation(mContext,
9289                    display, mFxSession, inTransaction, displayInfo.logicalWidth,
9290                    displayInfo.logicalHeight, display.getRotation(),
9291                    exitAnim, enterAnim);
9292            mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
9293        }
9294    }
9295
9296    private void stopFreezingDisplayLocked() {
9297        if (!mDisplayFrozen) {
9298            return;
9299        }
9300
9301        if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen
9302                || mClientFreezingScreen) {
9303            if (DEBUG_ORIENTATION) Slog.d(TAG,
9304                "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig
9305                + ", mAppsFreezingScreen=" + mAppsFreezingScreen
9306                + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen
9307                + ", mClientFreezingScreen=" + mClientFreezingScreen);
9308            return;
9309        }
9310
9311        mDisplayFrozen = false;
9312        mH.removeMessages(H.APP_FREEZE_TIMEOUT);
9313        mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
9314        if (PROFILE_ORIENTATION) {
9315            Debug.stopMethodTracing();
9316        }
9317
9318        boolean updateRotation = false;
9319
9320        final DisplayContent displayContent = getDefaultDisplayContentLocked();
9321        final int displayId = displayContent.getDisplayId();
9322        ScreenRotationAnimation screenRotationAnimation =
9323                mAnimator.getScreenRotationAnimationLocked(displayId);
9324        if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
9325                && screenRotationAnimation.hasScreenshot()) {
9326            if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation");
9327            // TODO(multidisplay): rotation on main screen only.
9328            DisplayInfo displayInfo = displayContent.getDisplayInfo();
9329            if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
9330                    mTransitionAnimationScale, displayInfo.logicalWidth,
9331                        displayInfo.logicalHeight)) {
9332                scheduleAnimationLocked();
9333            } else {
9334                screenRotationAnimation.kill();
9335                screenRotationAnimation = null;
9336                mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
9337                updateRotation = true;
9338            }
9339        } else {
9340            if (screenRotationAnimation != null) {
9341                screenRotationAnimation.kill();
9342                screenRotationAnimation = null;
9343                mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
9344            }
9345            updateRotation = true;
9346        }
9347
9348        mInputMonitor.thawInputDispatchingLw();
9349
9350        boolean configChanged;
9351
9352        // While the display is frozen we don't re-compute the orientation
9353        // to avoid inconsistent states.  However, something interesting
9354        // could have actually changed during that time so re-evaluate it
9355        // now to catch that.
9356        configChanged = updateOrientationFromAppTokensLocked(false);
9357
9358        // A little kludge: a lot could have happened while the
9359        // display was frozen, so now that we are coming back we
9360        // do a gc so that any remote references the system
9361        // processes holds on others can be released if they are
9362        // no longer needed.
9363        mH.removeMessages(H.FORCE_GC);
9364        mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000);
9365
9366        mScreenFrozenLock.release();
9367
9368        if (updateRotation) {
9369            if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
9370            configChanged |= updateRotationUncheckedLocked(false);
9371        }
9372
9373        if (configChanged) {
9374            mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
9375        }
9376    }
9377
9378    static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps,
9379            DisplayMetrics dm) {
9380        if (index < tokens.length) {
9381            String str = tokens[index];
9382            if (str != null && str.length() > 0) {
9383                try {
9384                    int val = Integer.parseInt(str);
9385                    return val;
9386                } catch (Exception e) {
9387                }
9388            }
9389        }
9390        if (defUnits == TypedValue.COMPLEX_UNIT_PX) {
9391            return defDps;
9392        }
9393        int val = (int)TypedValue.applyDimension(defUnits, defDps, dm);
9394        return val;
9395    }
9396
9397    void createWatermarkInTransaction() {
9398        if (mWatermark != null) {
9399            return;
9400        }
9401
9402        File file = new File("/system/etc/setup.conf");
9403        FileInputStream in = null;
9404        DataInputStream ind = null;
9405        try {
9406            in = new FileInputStream(file);
9407            ind = new DataInputStream(in);
9408            String line = ind.readLine();
9409            if (line != null) {
9410                String[] toks = line.split("%");
9411                if (toks != null && toks.length > 0) {
9412                    mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(),
9413                            mRealDisplayMetrics, mFxSession, toks);
9414                }
9415            }
9416        } catch (FileNotFoundException e) {
9417        } catch (IOException e) {
9418        } finally {
9419            if (ind != null) {
9420                try {
9421                    ind.close();
9422                } catch (IOException e) {
9423                }
9424            } else if (in != null) {
9425                try {
9426                    in.close();
9427                } catch (IOException e) {
9428                }
9429            }
9430        }
9431    }
9432
9433    @Override
9434    public void statusBarVisibilityChanged(int visibility) {
9435        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
9436                != PackageManager.PERMISSION_GRANTED) {
9437            throw new SecurityException("Caller does not hold permission "
9438                    + android.Manifest.permission.STATUS_BAR);
9439        }
9440
9441        synchronized (mWindowMap) {
9442            mLastStatusBarVisibility = visibility;
9443            visibility = mPolicy.adjustSystemUiVisibilityLw(visibility);
9444            updateStatusBarVisibilityLocked(visibility);
9445        }
9446    }
9447
9448    // TOOD(multidisplay): StatusBar on multiple screens?
9449    void updateStatusBarVisibilityLocked(int visibility) {
9450        mInputManager.setSystemUiVisibility(visibility);
9451        final WindowList windows = getDefaultWindowListLocked();
9452        final int N = windows.size();
9453        for (int i = 0; i < N; i++) {
9454            WindowState ws = windows.get(i);
9455            try {
9456                int curValue = ws.mSystemUiVisibility;
9457                int diff = curValue ^ visibility;
9458                // We are only interested in differences of one of the
9459                // clearable flags...
9460                diff &= View.SYSTEM_UI_CLEARABLE_FLAGS;
9461                // ...if it has actually been cleared.
9462                diff &= ~visibility;
9463                int newValue = (curValue&~diff) | (visibility&diff);
9464                if (newValue != curValue) {
9465                    ws.mSeq++;
9466                    ws.mSystemUiVisibility = newValue;
9467                }
9468                if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) {
9469                    ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq,
9470                            visibility, newValue, diff);
9471                }
9472            } catch (RemoteException e) {
9473                // so sorry
9474            }
9475        }
9476    }
9477
9478    @Override
9479    public void reevaluateStatusBarVisibility() {
9480        synchronized (mWindowMap) {
9481            int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility);
9482            updateStatusBarVisibilityLocked(visibility);
9483            performLayoutAndPlaceSurfacesLocked();
9484        }
9485    }
9486
9487    @Override
9488    public FakeWindow addFakeWindow(Looper looper,
9489            InputEventReceiver.Factory inputEventReceiverFactory,
9490            String name, int windowType, int layoutParamsFlags, boolean canReceiveKeys,
9491            boolean hasFocus, boolean touchFullscreen) {
9492        synchronized (mWindowMap) {
9493            FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputEventReceiverFactory,
9494                    name, windowType,
9495                    layoutParamsFlags, canReceiveKeys, hasFocus, touchFullscreen);
9496            int i=0;
9497            while (i<mFakeWindows.size()) {
9498                if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) {
9499                    break;
9500                }
9501            }
9502            mFakeWindows.add(i, fw);
9503            mInputMonitor.updateInputWindowsLw(true);
9504            return fw;
9505        }
9506    }
9507
9508    boolean removeFakeWindowLocked(FakeWindow window) {
9509        synchronized (mWindowMap) {
9510            if (mFakeWindows.remove(window)) {
9511                mInputMonitor.updateInputWindowsLw(true);
9512                return true;
9513            }
9514            return false;
9515        }
9516    }
9517
9518    // It is assumed that this method is called only by InputMethodManagerService.
9519    public void saveLastInputMethodWindowForTransition() {
9520        synchronized (mWindowMap) {
9521            // TODO(multidisplay): Pass in the displayID.
9522            DisplayContent displayContent = getDefaultDisplayContentLocked();
9523            if (mInputMethodWindow != null) {
9524                mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget);
9525            }
9526        }
9527    }
9528
9529    @Override
9530    public boolean hasNavigationBar() {
9531        return mPolicy.hasNavigationBar();
9532    }
9533
9534    @Override
9535    public void lockNow(Bundle options) {
9536        mPolicy.lockNow(options);
9537    }
9538
9539    @Override
9540    public boolean isSafeModeEnabled() {
9541        return mSafeMode;
9542    }
9543
9544    @Override
9545    public void showAssistant() {
9546        // TODO: What permission?
9547        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER)
9548                != PackageManager.PERMISSION_GRANTED) {
9549            return;
9550        }
9551        mPolicy.showAssistant();
9552    }
9553
9554    void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) {
9555        pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)");
9556        mPolicy.dump("    ", pw, args);
9557    }
9558
9559    void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) {
9560        pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)");
9561        mAnimator.dumpLocked(pw, "    ", dumpAll);
9562    }
9563
9564    void dumpTokensLocked(PrintWriter pw, boolean dumpAll) {
9565        pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)");
9566        if (mTokenMap.size() > 0) {
9567            pw.println("  All tokens:");
9568            Iterator<WindowToken> it = mTokenMap.values().iterator();
9569            while (it.hasNext()) {
9570                WindowToken token = it.next();
9571                pw.print("  "); pw.print(token);
9572                if (dumpAll) {
9573                    pw.println(':');
9574                    token.dump(pw, "    ");
9575                } else {
9576                    pw.println();
9577                }
9578            }
9579        }
9580        if (mWallpaperTokens.size() > 0) {
9581            pw.println();
9582            pw.println("  Wallpaper tokens:");
9583            for (int i=mWallpaperTokens.size()-1; i>=0; i--) {
9584                WindowToken token = mWallpaperTokens.get(i);
9585                pw.print("  Wallpaper #"); pw.print(i);
9586                        pw.print(' '); pw.print(token);
9587                if (dumpAll) {
9588                    pw.println(':');
9589                    token.dump(pw, "    ");
9590                } else {
9591                    pw.println();
9592                }
9593            }
9594        }
9595        if (mFinishedStarting.size() > 0) {
9596            pw.println();
9597            pw.println("  Finishing start of application tokens:");
9598            for (int i=mFinishedStarting.size()-1; i>=0; i--) {
9599                WindowToken token = mFinishedStarting.get(i);
9600                pw.print("  Finished Starting #"); pw.print(i);
9601                        pw.print(' '); pw.print(token);
9602                if (dumpAll) {
9603                    pw.println(':');
9604                    token.dump(pw, "    ");
9605                } else {
9606                    pw.println();
9607                }
9608            }
9609        }
9610        if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) {
9611            pw.println();
9612            if (mOpeningApps.size() > 0) {
9613                pw.print("  mOpeningApps="); pw.println(mOpeningApps);
9614            }
9615            if (mClosingApps.size() > 0) {
9616                pw.print("  mClosingApps="); pw.println(mClosingApps);
9617            }
9618        }
9619    }
9620
9621    void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) {
9622        pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)");
9623        if (mSessions.size() > 0) {
9624            Iterator<Session> it = mSessions.iterator();
9625            while (it.hasNext()) {
9626                Session s = it.next();
9627                pw.print("  Session "); pw.print(s); pw.println(':');
9628                s.dump(pw, "    ");
9629            }
9630        }
9631    }
9632
9633    void dumpWindowsLocked(PrintWriter pw, boolean dumpAll,
9634            ArrayList<WindowState> windows) {
9635        pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)");
9636        dumpWindowsNoHeaderLocked(pw, dumpAll, windows);
9637    }
9638
9639    void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll,
9640            ArrayList<WindowState> windows) {
9641        int j = 0;
9642        mTmpWindowsIterator.reset(REVERSE_ITERATOR);
9643        while (mTmpWindowsIterator.hasNext()) {
9644            final WindowState w = mTmpWindowsIterator.next();
9645            if (windows == null || windows.contains(w)) {
9646                pw.print("  Window #"); pw.print(j++); pw.print(' ');
9647                        pw.print(w); pw.println(":");
9648                w.dump(pw, "    ", dumpAll || windows != null);
9649            }
9650        }
9651        if (mInputMethodDialogs.size() > 0) {
9652            pw.println();
9653            pw.println("  Input method dialogs:");
9654            for (int i=mInputMethodDialogs.size()-1; i>=0; i--) {
9655                WindowState w = mInputMethodDialogs.get(i);
9656                if (windows == null || windows.contains(w)) {
9657                    pw.print("  IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w);
9658                }
9659            }
9660        }
9661        if (mPendingRemove.size() > 0) {
9662            pw.println();
9663            pw.println("  Remove pending for:");
9664            for (int i=mPendingRemove.size()-1; i>=0; i--) {
9665                WindowState w = mPendingRemove.get(i);
9666                if (windows == null || windows.contains(w)) {
9667                    pw.print("  Remove #"); pw.print(i); pw.print(' ');
9668                            pw.print(w);
9669                    if (dumpAll) {
9670                        pw.println(":");
9671                        w.dump(pw, "    ", true);
9672                    } else {
9673                        pw.println();
9674                    }
9675                }
9676            }
9677        }
9678        if (mForceRemoves != null && mForceRemoves.size() > 0) {
9679            pw.println();
9680            pw.println("  Windows force removing:");
9681            for (int i=mForceRemoves.size()-1; i>=0; i--) {
9682                WindowState w = mForceRemoves.get(i);
9683                pw.print("  Removing #"); pw.print(i); pw.print(' ');
9684                        pw.print(w);
9685                if (dumpAll) {
9686                    pw.println(":");
9687                    w.dump(pw, "    ", true);
9688                } else {
9689                    pw.println();
9690                }
9691            }
9692        }
9693        if (mDestroySurface.size() > 0) {
9694            pw.println();
9695            pw.println("  Windows waiting to destroy their surface:");
9696            for (int i=mDestroySurface.size()-1; i>=0; i--) {
9697                WindowState w = mDestroySurface.get(i);
9698                if (windows == null || windows.contains(w)) {
9699                    pw.print("  Destroy #"); 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 (mLosingFocus.size() > 0) {
9711            pw.println();
9712            pw.println("  Windows losing focus:");
9713            for (int i=mLosingFocus.size()-1; i>=0; i--) {
9714                WindowState w = mLosingFocus.get(i);
9715                if (windows == null || windows.contains(w)) {
9716                    pw.print("  Losing #"); 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 (mResizingWindows.size() > 0) {
9728            pw.println();
9729            pw.println("  Windows waiting to resize:");
9730            for (int i=mResizingWindows.size()-1; i>=0; i--) {
9731                WindowState w = mResizingWindows.get(i);
9732                if (windows == null || windows.contains(w)) {
9733                    pw.print("  Resizing #"); pw.print(i); pw.print(' ');
9734                            pw.print(w);
9735                    if (dumpAll) {
9736                        pw.println(":");
9737                        w.dump(pw, "    ", true);
9738                    } else {
9739                        pw.println();
9740                    }
9741                }
9742            }
9743        }
9744        if (mWaitingForDrawn.size() > 0) {
9745            pw.println();
9746            pw.println("  Clients waiting for these windows to be drawn:");
9747            for (int i=mWaitingForDrawn.size()-1; i>=0; i--) {
9748                Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(i);
9749                pw.print("  Waiting #"); pw.print(i); pw.print(' '); pw.print(pair.first);
9750                        pw.print(": "); pw.println(pair.second);
9751            }
9752        }
9753        pw.println();
9754        pw.println("  DisplayContents:");
9755        if (mDisplayReady) {
9756            DisplayContentsIterator dCIterator = new DisplayContentsIterator();
9757            while (dCIterator.hasNext()) {
9758                dCIterator.next().dump("    ", pw);
9759            }
9760        } else {
9761            pw.println("  NO DISPLAY");
9762        }
9763        pw.print("  mCurConfiguration="); pw.println(this.mCurConfiguration);
9764        pw.print("  mCurrentFocus="); pw.println(mCurrentFocus);
9765        if (mLastFocus != mCurrentFocus) {
9766            pw.print("  mLastFocus="); pw.println(mLastFocus);
9767        }
9768        pw.print("  mFocusedApp="); pw.println(mFocusedApp);
9769        if (mInputMethodTarget != null) {
9770            pw.print("  mInputMethodTarget="); pw.println(mInputMethodTarget);
9771        }
9772        pw.print("  mInTouchMode="); pw.print(mInTouchMode);
9773                pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
9774        if (dumpAll) {
9775            pw.print("  mSystemDecorRect="); pw.print(mSystemDecorRect.toShortString());
9776                    pw.print(" mSystemDecorLayer="); pw.print(mSystemDecorLayer);
9777                    pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString());
9778            if (mLastStatusBarVisibility != 0) {
9779                pw.print("  mLastStatusBarVisibility=0x");
9780                        pw.println(Integer.toHexString(mLastStatusBarVisibility));
9781            }
9782            if (mInputMethodWindow != null) {
9783                pw.print("  mInputMethodWindow="); pw.println(mInputMethodWindow);
9784            }
9785            pw.print("  mWallpaperTarget="); pw.println(mWallpaperTarget);
9786            if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) {
9787                pw.print("  mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget);
9788                pw.print("  mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget);
9789            }
9790            pw.print("  mLastWallpaperX="); pw.print(mLastWallpaperX);
9791                    pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
9792            if (mInputMethodAnimLayerAdjustment != 0 ||
9793                    mWallpaperAnimLayerAdjustment != 0) {
9794                pw.print("  mInputMethodAnimLayerAdjustment=");
9795                        pw.print(mInputMethodAnimLayerAdjustment);
9796                        pw.print("  mWallpaperAnimLayerAdjustment=");
9797                        pw.println(mWallpaperAnimLayerAdjustment);
9798            }
9799            pw.print("  mSystemBooted="); pw.print(mSystemBooted);
9800                    pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
9801            if (needsLayout()) {
9802                pw.print("  layoutNeeded on displays=");
9803                DisplayContentsIterator dcIterator = new DisplayContentsIterator();
9804                while (dcIterator.hasNext()) {
9805                    final DisplayContent displayContent = dcIterator.next();
9806                    if (displayContent.layoutNeeded) {
9807                        pw.print(displayContent.getDisplayId());
9808                    }
9809                }
9810                pw.println();
9811            }
9812            pw.print("  mTransactionSequence="); pw.println(mTransactionSequence);
9813            pw.print("  mDisplayFrozen="); pw.print(mDisplayFrozen);
9814                    pw.print(" windows="); pw.print(mWindowsFreezingScreen);
9815                    pw.print(" client="); pw.print(mClientFreezingScreen);
9816                    pw.print(" apps="); pw.print(mAppsFreezingScreen);
9817                    pw.print(" waitingForConfig="); pw.println(mWaitingForConfig);
9818            pw.print("  mRotation="); pw.print(mRotation);
9819                    pw.print(" mAltOrientation="); pw.println(mAltOrientation);
9820            pw.print("  mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation);
9821                    pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation);
9822            pw.print("  mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount);
9823            pw.print("  mWindowAnimationScale="); pw.print(mWindowAnimationScale);
9824                    pw.print(" mTransitionWindowAnimationScale="); pw.print(mTransitionAnimationScale);
9825                    pw.print(" mAnimatorDurationScale="); pw.println(mAnimatorDurationScale);
9826            pw.print("  mTraversalScheduled="); pw.println(mTraversalScheduled);
9827            pw.print("  mStartingIconInTransition="); pw.print(mStartingIconInTransition);
9828                    pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
9829            pw.println("  mLayoutToAnim:");
9830            mAppTransition.dump(pw);
9831        }
9832    }
9833
9834    boolean dumpWindows(PrintWriter pw, String name, String[] args,
9835            int opti, boolean dumpAll) {
9836        WindowList windows = new WindowList();
9837        if ("visible".equals(name)) {
9838            synchronized(mWindowMap) {
9839                mTmpWindowsIterator.reset(REVERSE_ITERATOR);
9840                while (mTmpWindowsIterator.hasNext()) {
9841                    final WindowState w = mTmpWindowsIterator.next();
9842                    if (w.mWinAnimator.mSurfaceShown) {
9843                        windows.add(w);
9844                    }
9845                }
9846            }
9847        } else {
9848            int objectId = 0;
9849            // See if this is an object ID.
9850            try {
9851                objectId = Integer.parseInt(name, 16);
9852                name = null;
9853            } catch (RuntimeException e) {
9854            }
9855            synchronized(mWindowMap) {
9856                mTmpWindowsIterator.reset(REVERSE_ITERATOR);
9857                while (mTmpWindowsIterator.hasNext()) {
9858                    final WindowState w = mTmpWindowsIterator.next();
9859                    if (name != null) {
9860                        if (w.mAttrs.getTitle().toString().contains(name)) {
9861                            windows.add(w);
9862                        }
9863                    } else if (System.identityHashCode(w) == objectId) {
9864                        windows.add(w);
9865                    }
9866                }
9867            }
9868        }
9869
9870        if (windows.size() <= 0) {
9871            return false;
9872        }
9873
9874        synchronized(mWindowMap) {
9875            dumpWindowsLocked(pw, dumpAll, windows);
9876        }
9877        return true;
9878    }
9879
9880    void dumpLastANRLocked(PrintWriter pw) {
9881        pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)");
9882        if (mLastANRState == null) {
9883            pw.println("  <no ANR has occurred since boot>");
9884        } else {
9885            pw.println(mLastANRState);
9886        }
9887    }
9888
9889    /**
9890     * Saves information about the state of the window manager at
9891     * the time an ANR occurred before anything else in the system changes
9892     * in response.
9893     *
9894     * @param appWindowToken The application that ANR'd, may be null.
9895     * @param windowState The window that ANR'd, may be null.
9896     */
9897    public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState) {
9898        StringWriter sw = new StringWriter();
9899        PrintWriter pw = new PrintWriter(sw);
9900        pw.println("  ANR time: " + DateFormat.getInstance().format(new Date()));
9901        if (appWindowToken != null) {
9902            pw.println("  Application at fault: " + appWindowToken.stringName);
9903        }
9904        if (windowState != null) {
9905            pw.println("  Window at fault: " + windowState.mAttrs.getTitle());
9906        }
9907        pw.println();
9908        dumpWindowsNoHeaderLocked(pw, true, null);
9909        pw.close();
9910        mLastANRState = sw.toString();
9911    }
9912
9913    @Override
9914    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
9915        if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
9916                != PackageManager.PERMISSION_GRANTED) {
9917            pw.println("Permission Denial: can't dump WindowManager from from pid="
9918                    + Binder.getCallingPid()
9919                    + ", uid=" + Binder.getCallingUid());
9920            return;
9921        }
9922
9923        boolean dumpAll = false;
9924
9925        int opti = 0;
9926        while (opti < args.length) {
9927            String opt = args[opti];
9928            if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
9929                break;
9930            }
9931            opti++;
9932            if ("-a".equals(opt)) {
9933                dumpAll = true;
9934            } else if ("-h".equals(opt)) {
9935                pw.println("Window manager dump options:");
9936                pw.println("  [-a] [-h] [cmd] ...");
9937                pw.println("  cmd may be one of:");
9938                pw.println("    l[astanr]: last ANR information");
9939                pw.println("    p[policy]: policy state");
9940                pw.println("    a[animator]: animator state");
9941                pw.println("    s[essions]: active sessions");
9942                pw.println("    t[okens]: token list");
9943                pw.println("    w[indows]: window list");
9944                pw.println("  cmd may also be a NAME to dump windows.  NAME may");
9945                pw.println("    be a partial substring in a window name, a");
9946                pw.println("    Window hex object identifier, or");
9947                pw.println("    \"all\" for all windows, or");
9948                pw.println("    \"visible\" for the visible windows.");
9949                pw.println("  -a: include all available server state.");
9950                return;
9951            } else {
9952                pw.println("Unknown argument: " + opt + "; use -h for help");
9953            }
9954        }
9955
9956        // Is the caller requesting to dump a particular piece of data?
9957        if (opti < args.length) {
9958            String cmd = args[opti];
9959            opti++;
9960            if ("lastanr".equals(cmd) || "l".equals(cmd)) {
9961                synchronized(mWindowMap) {
9962                    dumpLastANRLocked(pw);
9963                }
9964                return;
9965            } else if ("policy".equals(cmd) || "p".equals(cmd)) {
9966                synchronized(mWindowMap) {
9967                    dumpPolicyLocked(pw, args, true);
9968                }
9969                return;
9970            } else if ("animator".equals(cmd) || "a".equals(cmd)) {
9971                synchronized(mWindowMap) {
9972                    dumpAnimatorLocked(pw, args, true);
9973                }
9974                return;
9975            } else if ("sessions".equals(cmd) || "s".equals(cmd)) {
9976                synchronized(mWindowMap) {
9977                    dumpSessionsLocked(pw, true);
9978                }
9979                return;
9980            } else if ("tokens".equals(cmd) || "t".equals(cmd)) {
9981                synchronized(mWindowMap) {
9982                    dumpTokensLocked(pw, true);
9983                }
9984                return;
9985            } else if ("windows".equals(cmd) || "w".equals(cmd)) {
9986                synchronized(mWindowMap) {
9987                    dumpWindowsLocked(pw, true, null);
9988                }
9989                return;
9990            } else if ("all".equals(cmd) || "a".equals(cmd)) {
9991                synchronized(mWindowMap) {
9992                    dumpWindowsLocked(pw, true, null);
9993                }
9994                return;
9995            } else {
9996                // Dumping a single name?
9997                if (!dumpWindows(pw, cmd, args, opti, dumpAll)) {
9998                    pw.println("Bad window command, or no windows match: " + cmd);
9999                    pw.println("Use -h for help.");
10000                }
10001                return;
10002            }
10003        }
10004
10005        synchronized(mWindowMap) {
10006            pw.println();
10007            if (dumpAll) {
10008                pw.println("-------------------------------------------------------------------------------");
10009            }
10010            dumpLastANRLocked(pw);
10011            pw.println();
10012            if (dumpAll) {
10013                pw.println("-------------------------------------------------------------------------------");
10014            }
10015            dumpPolicyLocked(pw, args, dumpAll);
10016            pw.println();
10017            if (dumpAll) {
10018                pw.println("-------------------------------------------------------------------------------");
10019            }
10020            dumpAnimatorLocked(pw, args, dumpAll);
10021            pw.println();
10022            if (dumpAll) {
10023                pw.println("-------------------------------------------------------------------------------");
10024            }
10025            dumpSessionsLocked(pw, dumpAll);
10026            pw.println();
10027            if (dumpAll) {
10028                pw.println("-------------------------------------------------------------------------------");
10029            }
10030            dumpTokensLocked(pw, dumpAll);
10031            pw.println();
10032            if (dumpAll) {
10033                pw.println("-------------------------------------------------------------------------------");
10034            }
10035            dumpWindowsLocked(pw, dumpAll, null);
10036        }
10037    }
10038
10039    // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection).
10040    @Override
10041    public void monitor() {
10042        synchronized (mWindowMap) { }
10043    }
10044
10045    public interface OnHardKeyboardStatusChangeListener {
10046        public void onHardKeyboardStatusChange(boolean available, boolean enabled);
10047    }
10048
10049    void debugLayoutRepeats(final String msg, int pendingLayoutChanges) {
10050        if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) {
10051            Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" +
10052                    Integer.toHexString(pendingLayoutChanges));
10053        }
10054    }
10055
10056    private DisplayContent newDisplayContentLocked(final Display display) {
10057        DisplayContent displayContent = new DisplayContent(display);
10058        mDisplayContents.put(display.getDisplayId(), displayContent);
10059        final Rect rect = new Rect();
10060        DisplayInfo info = displayContent.getDisplayInfo();
10061        mDisplaySettings.getOverscanLocked(info.name, rect);
10062        info.overscanLeft = rect.left;
10063        info.overscanTop = rect.top;
10064        info.overscanRight = rect.right;
10065        info.overscanBottom = rect.bottom;
10066        mDisplayManagerService.setOverscan(display.getDisplayId(), rect.left, rect.top,
10067                rect.right, rect.bottom);
10068        mPolicy.setDisplayOverscan(displayContent.getDisplay(), rect.left, rect.top,
10069                rect.right, rect.bottom);
10070        return displayContent;
10071    }
10072
10073    public void createDisplayContentLocked(final Display display) {
10074        if (display == null) {
10075            throw new IllegalArgumentException("getDisplayContent: display must not be null");
10076        }
10077        newDisplayContentLocked(display);
10078    }
10079
10080    /**
10081     * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if
10082     * there is a Display for the displayId.
10083     * @param displayId The display the caller is interested in.
10084     * @return The DisplayContent associated with displayId or null if there is no Display for it.
10085     */
10086    public DisplayContent getDisplayContentLocked(final int displayId) {
10087        DisplayContent displayContent = mDisplayContents.get(displayId);
10088        if (displayContent == null) {
10089            final Display display = mDisplayManager.getDisplay(displayId);
10090            if (display != null) {
10091                displayContent = newDisplayContentLocked(display);
10092            }
10093        }
10094        return displayContent;
10095    }
10096
10097    class DisplayContentsIterator implements Iterator<DisplayContent> {
10098        private int cur;
10099
10100        void reset() {
10101            cur = 0;
10102        }
10103
10104        @Override
10105        public boolean hasNext() {
10106            return cur < mDisplayContents.size();
10107        }
10108
10109        @Override
10110        public DisplayContent next() {
10111            if (hasNext()) {
10112                return mDisplayContents.valueAt(cur++);
10113            }
10114            throw new NoSuchElementException();
10115        }
10116
10117        @Override
10118        public void remove() {
10119            throw new IllegalArgumentException("AllDisplayContentIterator.remove not implemented");
10120        }
10121    }
10122
10123    class AllWindowsIterator implements Iterator<WindowState> {
10124        private DisplayContent mDisplayContent;
10125        private DisplayContentsIterator mDisplayContentsIterator;
10126        private WindowList mWindowList;
10127        private int mWindowListIndex;
10128        private boolean mReverse;
10129
10130        AllWindowsIterator() {
10131            this(false);
10132        }
10133
10134        AllWindowsIterator(boolean reverse) {
10135            mDisplayContentsIterator = new DisplayContentsIterator();
10136            reset(reverse);
10137        }
10138
10139        void reset(boolean reverse) {
10140            mReverse = reverse;
10141            mDisplayContentsIterator.reset();
10142            if (mDisplayContentsIterator.hasNext()) {
10143                mDisplayContent = mDisplayContentsIterator.next();
10144                mWindowList = mDisplayContent.getWindowList();
10145                mWindowListIndex = reverse ? mWindowList.size() - 1 : 0;
10146            } else {
10147                mDisplayContent = null;
10148                mWindowList = null;
10149                mWindowListIndex = 0;
10150            }
10151        }
10152
10153        @Override
10154        public boolean hasNext() {
10155            if (mDisplayContent == null) {
10156                return false;
10157            }
10158            if (mReverse) {
10159                return mWindowListIndex >= 0;
10160            }
10161            return mWindowListIndex < mWindowList.size();
10162        }
10163
10164        @Override
10165        public WindowState next() {
10166            if (hasNext()) {
10167                WindowState win = mWindowList.get(mWindowListIndex);
10168                if (mReverse) {
10169                    mWindowListIndex--;
10170                    if (mWindowListIndex < 0 && mDisplayContentsIterator.hasNext()) {
10171                        mDisplayContent = mDisplayContentsIterator.next();
10172                        mWindowList = mDisplayContent.getWindowList();
10173                        mWindowListIndex = mWindowList.size() - 1;
10174                    }
10175                } else {
10176                    mWindowListIndex++;
10177                    if (mWindowListIndex >= mWindowList.size()
10178                            && mDisplayContentsIterator.hasNext()) {
10179                        mDisplayContent = mDisplayContentsIterator.next();
10180                        mWindowList = mDisplayContent.getWindowList();
10181                        mWindowListIndex = 0;
10182                    }
10183                }
10184                return win;
10185            }
10186            throw new NoSuchElementException();
10187        }
10188
10189        @Override
10190        public void remove() {
10191            throw new IllegalArgumentException("AllWindowsIterator.remove not implemented");
10192        }
10193    }
10194
10195    // There is an inherent assumption that this will never return null.
10196    public DisplayContent getDefaultDisplayContentLocked() {
10197        return getDisplayContentLocked(Display.DEFAULT_DISPLAY);
10198    }
10199
10200    public WindowList getDefaultWindowListLocked() {
10201        return getDefaultDisplayContentLocked().getWindowList();
10202    }
10203
10204    public DisplayInfo getDefaultDisplayInfoLocked() {
10205        return getDefaultDisplayContentLocked().getDisplayInfo();
10206    }
10207
10208    /**
10209     * Return the list of WindowStates associated on the passed display.
10210     * @param display The screen to return windows from.
10211     * @return The list of WindowStates on the screen, or null if the there is no screen.
10212     */
10213    public WindowList getWindowListLocked(final Display display) {
10214        return getWindowListLocked(display.getDisplayId());
10215    }
10216
10217    /**
10218     * Return the list of WindowStates associated on the passed display.
10219     * @param displayId The screen to return windows from.
10220     * @return The list of WindowStates on the screen, or null if the there is no screen.
10221     */
10222    public WindowList getWindowListLocked(final int displayId) {
10223        final DisplayContent displayContent = getDisplayContentLocked(displayId);
10224        return displayContent != null ? displayContent.getWindowList() : null;
10225    }
10226
10227    @Override
10228    public void onDisplayAdded(int displayId) {
10229        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0));
10230    }
10231
10232    private void handleDisplayAddedLocked(int displayId) {
10233        final Display display = mDisplayManager.getDisplay(displayId);
10234        if (display != null) {
10235            createDisplayContentLocked(display);
10236            displayReady(displayId);
10237        }
10238    }
10239
10240    @Override
10241    public void onDisplayRemoved(int displayId) {
10242        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0));
10243    }
10244
10245    private void handleDisplayRemovedLocked(int displayId) {
10246        final DisplayContent displayContent = getDisplayContentLocked(displayId);
10247        if (displayContent != null) {
10248            mDisplayContents.delete(displayId);
10249            WindowList windows = displayContent.getWindowList();
10250            while (!windows.isEmpty()) {
10251                final WindowState win = windows.get(windows.size() - 1);
10252                removeWindowLocked(win.mSession, win);
10253            }
10254        }
10255        mAnimator.removeDisplayLocked(displayId);
10256    }
10257
10258    @Override
10259    public void onDisplayChanged(int displayId) {
10260        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0));
10261    }
10262
10263    private void handleDisplayChangedLocked(int displayId) {
10264        final DisplayContent displayContent = getDisplayContentLocked(displayId);
10265        if (displayContent != null) {
10266            displayContent.updateDisplayInfo();
10267        }
10268    }
10269}
10270