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