WindowManagerService.java revision abe0aa78caf81b24af0b45700801fc1f867cfa0e
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                    if (minLayer > winAnim.mSurfaceLayer) {
5383                        minLayer = winAnim.mSurfaceLayer;
5384                    }
5385
5386                    // Don't include wallpaper in bounds calculation
5387                    if (!ws.mIsWallpaper) {
5388                        final Rect wf = ws.mFrame;
5389                        final Rect cr = ws.mContentInsets;
5390                        int left = wf.left + cr.left;
5391                        int top = wf.top + cr.top;
5392                        int right = wf.right - cr.right;
5393                        int bottom = wf.bottom - cr.bottom;
5394                        frame.union(left, top, right, bottom);
5395                    }
5396
5397                    if (ws.mAppToken != null && ws.mAppToken.token == appToken &&
5398                            ws.isDisplayedLw()) {
5399                        screenshotReady = true;
5400                    }
5401
5402                    if (fullscreen) {
5403                        // No point in continuing down through windows.
5404                        break;
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 (retryCount > MAX_SCREENSHOT_RETRIES)  Slog.i(TAG, "Screenshot max retries " +
5479                retryCount + " of " + appToken + " appWin=" + (appWin == null ?
5480                        "null" : (appWin + " drawState=" + appWin.mWinAnimator.mDrawState)));
5481
5482        if (rawss == null) {
5483            Slog.w(TAG, "Screenshot failure taking screenshot for (" + dw + "x" + dh
5484                    + ") to layer " + maxLayer);
5485            return null;
5486        }
5487
5488        Bitmap bm = Bitmap.createBitmap(width, height, rawss.getConfig());
5489        Matrix matrix = new Matrix();
5490        ScreenRotationAnimation.createRotationMatrix(rot, dw, dh, matrix);
5491        matrix.postTranslate(-FloatMath.ceil(frame.left*scale), -FloatMath.ceil(frame.top*scale));
5492        Canvas canvas = new Canvas(bm);
5493        canvas.drawBitmap(rawss, matrix, null);
5494        canvas.setBitmap(null);
5495
5496        if (true || DEBUG_SCREENSHOT) {
5497            // TEST IF IT's ALL BLACK
5498            int[] buffer = new int[bm.getWidth() * bm.getHeight()];
5499            bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight());
5500            boolean allBlack = true;
5501            for (int i = 0; i < buffer.length; i++) {
5502                if (buffer[i] != Color.BLACK) {
5503                    allBlack = false;
5504                    break;
5505                }
5506            }
5507            if (allBlack) {
5508                Slog.i(TAG, "Screenshot " + appWin + " was all black! mSurfaceLayer=" +
5509                        (appWin != null ? appWin.mWinAnimator.mSurfaceLayer : "null") +
5510                        " minLayer=" + minLayer + " maxLayer=" + maxLayer);
5511            }
5512        }
5513
5514        rawss.recycle();
5515        return bm;
5516    }
5517
5518    /**
5519     * Freeze rotation changes.  (Enable "rotation lock".)
5520     * Persists across reboots.
5521     * @param rotation The desired rotation to freeze to, or -1 to use the
5522     * current rotation.
5523     */
5524    @Override
5525    public void freezeRotation(int rotation) {
5526        if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
5527                "freezeRotation()")) {
5528            throw new SecurityException("Requires SET_ORIENTATION permission");
5529        }
5530        if (rotation < -1 || rotation > Surface.ROTATION_270) {
5531            throw new IllegalArgumentException("Rotation argument must be -1 or a valid "
5532                    + "rotation constant.");
5533        }
5534
5535        if (DEBUG_ORIENTATION) Slog.v(TAG, "freezeRotation: mRotation=" + mRotation);
5536
5537        long origId = Binder.clearCallingIdentity();
5538        try {
5539            mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED,
5540                    rotation == -1 ? mRotation : rotation);
5541        } finally {
5542            Binder.restoreCallingIdentity(origId);
5543        }
5544
5545        updateRotationUnchecked(false, false);
5546    }
5547
5548    /**
5549     * Thaw rotation changes.  (Disable "rotation lock".)
5550     * Persists across reboots.
5551     */
5552    @Override
5553    public void thawRotation() {
5554        if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
5555                "thawRotation()")) {
5556            throw new SecurityException("Requires SET_ORIENTATION permission");
5557        }
5558
5559        if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation);
5560
5561        long origId = Binder.clearCallingIdentity();
5562        try {
5563            mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE,
5564                    777); // rot not used
5565        } finally {
5566            Binder.restoreCallingIdentity(origId);
5567        }
5568
5569        updateRotationUnchecked(false, false);
5570    }
5571
5572    /**
5573     * Recalculate the current rotation.
5574     *
5575     * Called by the window manager policy whenever the state of the system changes
5576     * such that the current rotation might need to be updated, such as when the
5577     * device is docked or rotated into a new posture.
5578     */
5579    @Override
5580    public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
5581        updateRotationUnchecked(alwaysSendConfiguration, forceRelayout);
5582    }
5583
5584    /**
5585     * Temporarily pauses rotation changes until resumed.
5586     *
5587     * This can be used to prevent rotation changes from occurring while the user is
5588     * performing certain operations, such as drag and drop.
5589     *
5590     * This call nests and must be matched by an equal number of calls to
5591     * {@link #resumeRotationLocked}.
5592     */
5593    void pauseRotationLocked() {
5594        mDeferredRotationPauseCount += 1;
5595    }
5596
5597    /**
5598     * Resumes normal rotation changes after being paused.
5599     */
5600    void resumeRotationLocked() {
5601        if (mDeferredRotationPauseCount > 0) {
5602            mDeferredRotationPauseCount -= 1;
5603            if (mDeferredRotationPauseCount == 0) {
5604                boolean changed = updateRotationUncheckedLocked(false);
5605                if (changed) {
5606                    mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
5607                }
5608            }
5609        }
5610    }
5611
5612    public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) {
5613        if(DEBUG_ORIENTATION) Slog.v(TAG, "updateRotationUnchecked("
5614                   + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")");
5615
5616        long origId = Binder.clearCallingIdentity();
5617        boolean changed;
5618        synchronized(mWindowMap) {
5619            changed = updateRotationUncheckedLocked(false);
5620            if (!changed || forceRelayout) {
5621                getDefaultDisplayContentLocked().layoutNeeded = true;
5622                performLayoutAndPlaceSurfacesLocked();
5623            }
5624        }
5625
5626        if (changed || alwaysSendConfiguration) {
5627            sendNewConfiguration();
5628        }
5629
5630        Binder.restoreCallingIdentity(origId);
5631    }
5632
5633    // TODO(multidisplay): Rotate any display?
5634    /**
5635     * Updates the current rotation.
5636     *
5637     * Returns true if the rotation has been changed.  In this case YOU
5638     * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN.
5639     */
5640    public boolean updateRotationUncheckedLocked(boolean inTransaction) {
5641        if (mDeferredRotationPauseCount > 0) {
5642            // Rotation updates have been paused temporarily.  Defer the update until
5643            // updates have been resumed.
5644            if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, rotation is paused.");
5645            return false;
5646        }
5647
5648        ScreenRotationAnimation screenRotationAnimation =
5649                mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
5650        if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
5651            // Rotation updates cannot be performed while the previous rotation change
5652            // animation is still in progress.  Skip this update.  We will try updating
5653            // again after the animation is finished and the display is unfrozen.
5654            if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, animation in progress.");
5655            return false;
5656        }
5657
5658        if (!mDisplayEnabled) {
5659            // No point choosing a rotation if the display is not enabled.
5660            if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, display is not enabled.");
5661            return false;
5662        }
5663
5664        // TODO: Implement forced rotation changes.
5665        //       Set mAltOrientation to indicate that the application is receiving
5666        //       an orientation that has different metrics than it expected.
5667        //       eg. Portrait instead of Landscape.
5668
5669        int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation);
5670        boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw(
5671                mForcedAppOrientation, rotation);
5672
5673        if (DEBUG_ORIENTATION) {
5674            Slog.v(TAG, "Application requested orientation "
5675                    + mForcedAppOrientation + ", got rotation " + rotation
5676                    + " which has " + (altOrientation ? "incompatible" : "compatible")
5677                    + " metrics");
5678        }
5679
5680        if (mRotation == rotation && mAltOrientation == altOrientation) {
5681            // No change.
5682            return false;
5683        }
5684
5685        if (DEBUG_ORIENTATION) {
5686            Slog.v(TAG,
5687                "Rotation changed to " + rotation + (altOrientation ? " (alt)" : "")
5688                + " from " + mRotation + (mAltOrientation ? " (alt)" : "")
5689                + ", forceApp=" + mForcedAppOrientation);
5690        }
5691
5692        mRotation = rotation;
5693        mAltOrientation = altOrientation;
5694        mPolicy.setRotationLw(mRotation);
5695
5696        mWindowsFreezingScreen = true;
5697        mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
5698        mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION);
5699        mWaitingForConfig = true;
5700        getDefaultDisplayContentLocked().layoutNeeded = true;
5701        final int[] anim = new int[2];
5702        if (mAnimator.isDimmingLocked(Display.DEFAULT_DISPLAY)) {
5703            anim[0] = anim[1] = 0;
5704        } else {
5705            mPolicy.selectRotationAnimationLw(anim);
5706        }
5707        startFreezingDisplayLocked(inTransaction, anim[0], anim[1]);
5708        // startFreezingDisplayLocked can reset the ScreenRotationAnimation.
5709        screenRotationAnimation =
5710                mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
5711
5712        // We need to update our screen size information to match the new
5713        // rotation.  Note that this is redundant with the later call to
5714        // sendNewConfiguration() that must be called after this function
5715        // returns...  however we need to do the screen size part of that
5716        // before then so we have the correct size to use when initializing
5717        // the rotation animation for the new rotation.
5718        computeScreenConfigurationLocked(null);
5719
5720        final DisplayContent displayContent = getDefaultDisplayContentLocked();
5721        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
5722        if (!inTransaction) {
5723            if (SHOW_TRANSACTIONS) {
5724                Slog.i(TAG, ">>> OPEN TRANSACTION setRotationUnchecked");
5725            }
5726            SurfaceControl.openTransaction();
5727        }
5728        try {
5729            // NOTE: We disable the rotation in the emulator because
5730            //       it doesn't support hardware OpenGL emulation yet.
5731            if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
5732                    && screenRotationAnimation.hasScreenshot()) {
5733                if (screenRotationAnimation.setRotationInTransaction(
5734                        rotation, mFxSession,
5735                        MAX_ANIMATION_DURATION, mTransitionAnimationScale,
5736                        displayInfo.logicalWidth, displayInfo.logicalHeight)) {
5737                    scheduleAnimationLocked();
5738                }
5739            }
5740
5741            mDisplayManagerService.performTraversalInTransactionFromWindowManager();
5742        } finally {
5743            if (!inTransaction) {
5744                SurfaceControl.closeTransaction();
5745                if (SHOW_LIGHT_TRANSACTIONS) {
5746                    Slog.i(TAG, "<<< CLOSE TRANSACTION setRotationUnchecked");
5747                }
5748            }
5749        }
5750
5751        final WindowList windows = displayContent.getWindowList();
5752        for (int i = windows.size() - 1; i >= 0; i--) {
5753            WindowState w = windows.get(i);
5754            if (w.mHasSurface) {
5755                if (DEBUG_ORIENTATION) Slog.v(TAG, "Set mOrientationChanging of " + w);
5756                w.mOrientationChanging = true;
5757                mInnerFields.mOrientationChangeComplete = false;
5758            }
5759            w.mLastFreezeDuration = 0;
5760        }
5761
5762        for (int i=mRotationWatchers.size()-1; i>=0; i--) {
5763            try {
5764                mRotationWatchers.get(i).onRotationChanged(rotation);
5765            } catch (RemoteException e) {
5766            }
5767        }
5768
5769        //TODO (multidisplay): Magnification is supported only for the default display.
5770        if (mDisplayMagnifier != null
5771                && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) {
5772            mDisplayMagnifier.onRotationChangedLocked(getDefaultDisplayContentLocked(), rotation);
5773        }
5774
5775        return true;
5776    }
5777
5778    @Override
5779    public int getRotation() {
5780        return mRotation;
5781    }
5782
5783    @Override
5784    public boolean isRotationFrozen() {
5785        return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED;
5786    }
5787
5788    @Override
5789    public int watchRotation(IRotationWatcher watcher) {
5790        final IBinder watcherBinder = watcher.asBinder();
5791        IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
5792            @Override
5793            public void binderDied() {
5794                synchronized (mWindowMap) {
5795                    for (int i=0; i<mRotationWatchers.size(); i++) {
5796                        if (watcherBinder == mRotationWatchers.get(i).asBinder()) {
5797                            IRotationWatcher removed = mRotationWatchers.remove(i);
5798                            if (removed != null) {
5799                                removed.asBinder().unlinkToDeath(this, 0);
5800                            }
5801                            i--;
5802                        }
5803                    }
5804                }
5805            }
5806        };
5807
5808        synchronized (mWindowMap) {
5809            try {
5810                watcher.asBinder().linkToDeath(dr, 0);
5811                mRotationWatchers.add(watcher);
5812            } catch (RemoteException e) {
5813                // Client died, no cleanup needed.
5814            }
5815
5816            return mRotation;
5817        }
5818    }
5819
5820    @Override
5821    public void removeRotationWatcher(IRotationWatcher watcher) {
5822        final IBinder watcherBinder = watcher.asBinder();
5823        synchronized (mWindowMap) {
5824            for (int i=0; i<mRotationWatchers.size(); i++) {
5825                if (watcherBinder == mRotationWatchers.get(i).asBinder()) {
5826                    mRotationWatchers.remove(i);
5827                    i--;
5828                }
5829            }
5830        }
5831    }
5832
5833    /**
5834     * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact
5835     * theme attribute) on devices that feature a physical options menu key attempt to position
5836     * their menu panel window along the edge of the screen nearest the physical menu key.
5837     * This lowers the travel distance between invoking the menu panel and selecting
5838     * a menu option.
5839     *
5840     * This method helps control where that menu is placed. Its current implementation makes
5841     * assumptions about the menu key and its relationship to the screen based on whether
5842     * the device's natural orientation is portrait (width < height) or landscape.
5843     *
5844     * The menu key is assumed to be located along the bottom edge of natural-portrait
5845     * devices and along the right edge of natural-landscape devices. If these assumptions
5846     * do not hold for the target device, this method should be changed to reflect that.
5847     *
5848     * @return A {@link Gravity} value for placing the options menu window
5849     */
5850    @Override
5851    public int getPreferredOptionsPanelGravity() {
5852        synchronized (mWindowMap) {
5853            final int rotation = getRotation();
5854
5855            // TODO(multidisplay): Assume that such devices physical keys are on the main screen.
5856            final DisplayContent displayContent = getDefaultDisplayContentLocked();
5857            if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) {
5858                // On devices with a natural orientation of portrait
5859                switch (rotation) {
5860                    default:
5861                    case Surface.ROTATION_0:
5862                        return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
5863                    case Surface.ROTATION_90:
5864                        return Gravity.RIGHT | Gravity.BOTTOM;
5865                    case Surface.ROTATION_180:
5866                        return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
5867                    case Surface.ROTATION_270:
5868                        return Gravity.START | Gravity.BOTTOM;
5869                }
5870            }
5871
5872            // On devices with a natural orientation of landscape
5873            switch (rotation) {
5874                default:
5875                case Surface.ROTATION_0:
5876                    return Gravity.RIGHT | Gravity.BOTTOM;
5877                case Surface.ROTATION_90:
5878                    return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
5879                case Surface.ROTATION_180:
5880                    return Gravity.START | Gravity.BOTTOM;
5881                case Surface.ROTATION_270:
5882                    return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
5883            }
5884        }
5885    }
5886
5887    /**
5888     * Starts the view server on the specified port.
5889     *
5890     * @param port The port to listener to.
5891     *
5892     * @return True if the server was successfully started, false otherwise.
5893     *
5894     * @see com.android.server.wm.ViewServer
5895     * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT
5896     */
5897    @Override
5898    public boolean startViewServer(int port) {
5899        if (isSystemSecure()) {
5900            return false;
5901        }
5902
5903        if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) {
5904            return false;
5905        }
5906
5907        if (port < 1024) {
5908            return false;
5909        }
5910
5911        if (mViewServer != null) {
5912            if (!mViewServer.isRunning()) {
5913                try {
5914                    return mViewServer.start();
5915                } catch (IOException e) {
5916                    Slog.w(TAG, "View server did not start");
5917                }
5918            }
5919            return false;
5920        }
5921
5922        try {
5923            mViewServer = new ViewServer(this, port);
5924            return mViewServer.start();
5925        } catch (IOException e) {
5926            Slog.w(TAG, "View server did not start");
5927        }
5928        return false;
5929    }
5930
5931    private boolean isSystemSecure() {
5932        return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) &&
5933                "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
5934    }
5935
5936    /**
5937     * Stops the view server if it exists.
5938     *
5939     * @return True if the server stopped, false if it wasn't started or
5940     *         couldn't be stopped.
5941     *
5942     * @see com.android.server.wm.ViewServer
5943     */
5944    @Override
5945    public boolean stopViewServer() {
5946        if (isSystemSecure()) {
5947            return false;
5948        }
5949
5950        if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) {
5951            return false;
5952        }
5953
5954        if (mViewServer != null) {
5955            return mViewServer.stop();
5956        }
5957        return false;
5958    }
5959
5960    /**
5961     * Indicates whether the view server is running.
5962     *
5963     * @return True if the server is running, false otherwise.
5964     *
5965     * @see com.android.server.wm.ViewServer
5966     */
5967    @Override
5968    public boolean isViewServerRunning() {
5969        if (isSystemSecure()) {
5970            return false;
5971        }
5972
5973        if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) {
5974            return false;
5975        }
5976
5977        return mViewServer != null && mViewServer.isRunning();
5978    }
5979
5980    /**
5981     * Lists all availble windows in the system. The listing is written in the
5982     * specified Socket's output stream with the following syntax:
5983     * windowHashCodeInHexadecimal windowName
5984     * Each line of the ouput represents a different window.
5985     *
5986     * @param client The remote client to send the listing to.
5987     * @return False if an error occured, true otherwise.
5988     */
5989    boolean viewServerListWindows(Socket client) {
5990        if (isSystemSecure()) {
5991            return false;
5992        }
5993
5994        boolean result = true;
5995
5996        WindowList windows = new WindowList();
5997        synchronized (mWindowMap) {
5998            //noinspection unchecked
5999            DisplayContentsIterator iterator = new DisplayContentsIterator();
6000            while(iterator.hasNext()) {
6001                windows.addAll(iterator.next().getWindowList());
6002            }
6003        }
6004
6005        BufferedWriter out = null;
6006
6007        // Any uncaught exception will crash the system process
6008        try {
6009            OutputStream clientStream = client.getOutputStream();
6010            out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
6011
6012            final int count = windows.size();
6013            for (int i = 0; i < count; i++) {
6014                final WindowState w = windows.get(i);
6015                out.write(Integer.toHexString(System.identityHashCode(w)));
6016                out.write(' ');
6017                out.append(w.mAttrs.getTitle());
6018                out.write('\n');
6019            }
6020
6021            out.write("DONE.\n");
6022            out.flush();
6023        } catch (Exception e) {
6024            result = false;
6025        } finally {
6026            if (out != null) {
6027                try {
6028                    out.close();
6029                } catch (IOException e) {
6030                    result = false;
6031                }
6032            }
6033        }
6034
6035        return result;
6036    }
6037
6038    // TODO(multidisplay): Extend to multiple displays.
6039    /**
6040     * Returns the focused window in the following format:
6041     * windowHashCodeInHexadecimal windowName
6042     *
6043     * @param client The remote client to send the listing to.
6044     * @return False if an error occurred, true otherwise.
6045     */
6046    boolean viewServerGetFocusedWindow(Socket client) {
6047        if (isSystemSecure()) {
6048            return false;
6049        }
6050
6051        boolean result = true;
6052
6053        WindowState focusedWindow = getFocusedWindow();
6054
6055        BufferedWriter out = null;
6056
6057        // Any uncaught exception will crash the system process
6058        try {
6059            OutputStream clientStream = client.getOutputStream();
6060            out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
6061
6062            if(focusedWindow != null) {
6063                out.write(Integer.toHexString(System.identityHashCode(focusedWindow)));
6064                out.write(' ');
6065                out.append(focusedWindow.mAttrs.getTitle());
6066            }
6067            out.write('\n');
6068            out.flush();
6069        } catch (Exception e) {
6070            result = false;
6071        } finally {
6072            if (out != null) {
6073                try {
6074                    out.close();
6075                } catch (IOException e) {
6076                    result = false;
6077                }
6078            }
6079        }
6080
6081        return result;
6082    }
6083
6084    /**
6085     * Sends a command to a target window. The result of the command, if any, will be
6086     * written in the output stream of the specified socket.
6087     *
6088     * The parameters must follow this syntax:
6089     * windowHashcode extra
6090     *
6091     * Where XX is the length in characeters of the windowTitle.
6092     *
6093     * The first parameter is the target window. The window with the specified hashcode
6094     * will be the target. If no target can be found, nothing happens. The extra parameters
6095     * will be delivered to the target window and as parameters to the command itself.
6096     *
6097     * @param client The remote client to sent the result, if any, to.
6098     * @param command The command to execute.
6099     * @param parameters The command parameters.
6100     *
6101     * @return True if the command was successfully delivered, false otherwise. This does
6102     *         not indicate whether the command itself was successful.
6103     */
6104    boolean viewServerWindowCommand(Socket client, String command, String parameters) {
6105        if (isSystemSecure()) {
6106            return false;
6107        }
6108
6109        boolean success = true;
6110        Parcel data = null;
6111        Parcel reply = null;
6112
6113        BufferedWriter out = null;
6114
6115        // Any uncaught exception will crash the system process
6116        try {
6117            // Find the hashcode of the window
6118            int index = parameters.indexOf(' ');
6119            if (index == -1) {
6120                index = parameters.length();
6121            }
6122            final String code = parameters.substring(0, index);
6123            int hashCode = (int) Long.parseLong(code, 16);
6124
6125            // Extract the command's parameter after the window description
6126            if (index < parameters.length()) {
6127                parameters = parameters.substring(index + 1);
6128            } else {
6129                parameters = "";
6130            }
6131
6132            final WindowState window = findWindow(hashCode);
6133            if (window == null) {
6134                return false;
6135            }
6136
6137            data = Parcel.obtain();
6138            data.writeInterfaceToken("android.view.IWindow");
6139            data.writeString(command);
6140            data.writeString(parameters);
6141            data.writeInt(1);
6142            ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0);
6143
6144            reply = Parcel.obtain();
6145
6146            final IBinder binder = window.mClient.asBinder();
6147            // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER
6148            binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
6149
6150            reply.readException();
6151
6152            if (!client.isOutputShutdown()) {
6153                out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
6154                out.write("DONE\n");
6155                out.flush();
6156            }
6157
6158        } catch (Exception e) {
6159            Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e);
6160            success = false;
6161        } finally {
6162            if (data != null) {
6163                data.recycle();
6164            }
6165            if (reply != null) {
6166                reply.recycle();
6167            }
6168            if (out != null) {
6169                try {
6170                    out.close();
6171                } catch (IOException e) {
6172
6173                }
6174            }
6175        }
6176
6177        return success;
6178    }
6179
6180    public void addWindowChangeListener(WindowChangeListener listener) {
6181        synchronized(mWindowMap) {
6182            mWindowChangeListeners.add(listener);
6183        }
6184    }
6185
6186    public void removeWindowChangeListener(WindowChangeListener listener) {
6187        synchronized(mWindowMap) {
6188            mWindowChangeListeners.remove(listener);
6189        }
6190    }
6191
6192    private void notifyWindowsChanged() {
6193        WindowChangeListener[] windowChangeListeners;
6194        synchronized(mWindowMap) {
6195            if(mWindowChangeListeners.isEmpty()) {
6196                return;
6197            }
6198            windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
6199            windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
6200        }
6201        int N = windowChangeListeners.length;
6202        for(int i = 0; i < N; i++) {
6203            windowChangeListeners[i].windowsChanged();
6204        }
6205    }
6206
6207    private void notifyFocusChanged() {
6208        WindowChangeListener[] windowChangeListeners;
6209        synchronized(mWindowMap) {
6210            if(mWindowChangeListeners.isEmpty()) {
6211                return;
6212            }
6213            windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
6214            windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
6215        }
6216        int N = windowChangeListeners.length;
6217        for(int i = 0; i < N; i++) {
6218            windowChangeListeners[i].focusChanged();
6219        }
6220    }
6221
6222    private WindowState findWindow(int hashCode) {
6223        if (hashCode == -1) {
6224            // TODO(multidisplay): Extend to multiple displays.
6225            return getFocusedWindow();
6226        }
6227
6228        synchronized (mWindowMap) {
6229            final AllWindowsIterator iterator = new AllWindowsIterator();
6230            while (iterator.hasNext()) {
6231                final WindowState w = iterator.next();
6232                if (System.identityHashCode(w) == hashCode) {
6233                    return w;
6234                }
6235            }
6236        }
6237
6238        return null;
6239    }
6240
6241    /*
6242     * Instruct the Activity Manager to fetch the current configuration and broadcast
6243     * that to config-changed listeners if appropriate.
6244     */
6245    void sendNewConfiguration() {
6246        try {
6247            mActivityManager.updateConfiguration(null);
6248        } catch (RemoteException e) {
6249        }
6250    }
6251
6252    public Configuration computeNewConfiguration() {
6253        synchronized (mWindowMap) {
6254            Configuration config = computeNewConfigurationLocked();
6255            if (config == null && mWaitingForConfig) {
6256                // Nothing changed but we are waiting for something... stop that!
6257                mWaitingForConfig = false;
6258                mLastFinishedFreezeSource = "new-config";
6259                performLayoutAndPlaceSurfacesLocked();
6260            }
6261            return config;
6262        }
6263    }
6264
6265    Configuration computeNewConfigurationLocked() {
6266        Configuration config = new Configuration();
6267        config.fontScale = 0;
6268        if (!computeScreenConfigurationLocked(config)) {
6269            return null;
6270        }
6271        return config;
6272    }
6273
6274    private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int dw, int dh) {
6275        // TODO: Multidisplay: for now only use with default display.
6276        final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation);
6277        if (width < displayInfo.smallestNominalAppWidth) {
6278            displayInfo.smallestNominalAppWidth = width;
6279        }
6280        if (width > displayInfo.largestNominalAppWidth) {
6281            displayInfo.largestNominalAppWidth = width;
6282        }
6283        final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation);
6284        if (height < displayInfo.smallestNominalAppHeight) {
6285            displayInfo.smallestNominalAppHeight = height;
6286        }
6287        if (height > displayInfo.largestNominalAppHeight) {
6288            displayInfo.largestNominalAppHeight = height;
6289        }
6290    }
6291
6292    private int reduceConfigLayout(int curLayout, int rotation, float density,
6293            int dw, int dh) {
6294        // TODO: Multidisplay: for now only use with default display.
6295        // Get the app screen size at this rotation.
6296        int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation);
6297        int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation);
6298
6299        // Compute the screen layout size class for this rotation.
6300        int longSize = w;
6301        int shortSize = h;
6302        if (longSize < shortSize) {
6303            int tmp = longSize;
6304            longSize = shortSize;
6305            shortSize = tmp;
6306        }
6307        longSize = (int)(longSize/density);
6308        shortSize = (int)(shortSize/density);
6309        return Configuration.reduceScreenLayout(curLayout, longSize, shortSize);
6310    }
6311
6312    private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated,
6313                  int dw, int dh, float density, Configuration outConfig) {
6314        // TODO: Multidisplay: for now only use with default display.
6315
6316        // We need to determine the smallest width that will occur under normal
6317        // operation.  To this, start with the base screen size and compute the
6318        // width under the different possible rotations.  We need to un-rotate
6319        // the current screen dimensions before doing this.
6320        int unrotDw, unrotDh;
6321        if (rotated) {
6322            unrotDw = dh;
6323            unrotDh = dw;
6324        } else {
6325            unrotDw = dw;
6326            unrotDh = dh;
6327        }
6328        displayInfo.smallestNominalAppWidth = 1<<30;
6329        displayInfo.smallestNominalAppHeight = 1<<30;
6330        displayInfo.largestNominalAppWidth = 0;
6331        displayInfo.largestNominalAppHeight = 0;
6332        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, unrotDw, unrotDh);
6333        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, unrotDh, unrotDw);
6334        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, unrotDw, unrotDh);
6335        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, unrotDh, unrotDw);
6336        int sl = Configuration.resetScreenLayout(outConfig.screenLayout);
6337        sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh);
6338        sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw);
6339        sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh);
6340        sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw);
6341        outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density);
6342        outConfig.screenLayout = sl;
6343    }
6344
6345    private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm,
6346            int dw, int dh) {
6347        // TODO: Multidisplay: for now only use with default display.
6348        dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation);
6349        dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation);
6350        float scale = CompatibilityInfo.computeCompatibleScaling(dm, null);
6351        int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f);
6352        if (curSize == 0 || size < curSize) {
6353            curSize = size;
6354        }
6355        return curSize;
6356    }
6357
6358    private int computeCompatSmallestWidth(boolean rotated, DisplayMetrics dm, int dw, int dh) {
6359        // TODO: Multidisplay: for now only use with default display.
6360        mTmpDisplayMetrics.setTo(dm);
6361        final DisplayMetrics tmpDm = mTmpDisplayMetrics;
6362        final int unrotDw, unrotDh;
6363        if (rotated) {
6364            unrotDw = dh;
6365            unrotDh = dw;
6366        } else {
6367            unrotDw = dw;
6368            unrotDh = dh;
6369        }
6370        int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, tmpDm, unrotDw, unrotDh);
6371        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, tmpDm, unrotDh, unrotDw);
6372        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, tmpDm, unrotDw, unrotDh);
6373        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, tmpDm, unrotDh, unrotDw);
6374        return sw;
6375    }
6376
6377    boolean computeScreenConfigurationLocked(Configuration config) {
6378        if (!mDisplayReady) {
6379            return false;
6380        }
6381
6382        // TODO(multidisplay): For now, apply Configuration to main screen only.
6383        final DisplayContent displayContent = getDefaultDisplayContentLocked();
6384
6385        // Use the effective "visual" dimensions based on current rotation
6386        final boolean rotated = (mRotation == Surface.ROTATION_90
6387                || mRotation == Surface.ROTATION_270);
6388        final int realdw = rotated ?
6389                displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth;
6390        final int realdh = rotated ?
6391                displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight;
6392        int dw = realdw;
6393        int dh = realdh;
6394
6395        if (mAltOrientation) {
6396            if (realdw > realdh) {
6397                // Turn landscape into portrait.
6398                int maxw = (int)(realdh/1.3f);
6399                if (maxw < realdw) {
6400                    dw = maxw;
6401                }
6402            } else {
6403                // Turn portrait into landscape.
6404                int maxh = (int)(realdw/1.3f);
6405                if (maxh < realdh) {
6406                    dh = maxh;
6407                }
6408            }
6409        }
6410
6411        if (config != null) {
6412            config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT :
6413                    Configuration.ORIENTATION_LANDSCAPE;
6414        }
6415
6416        // Update application display metrics.
6417        final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation);
6418        final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation);
6419        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
6420        synchronized(displayContent.mDisplaySizeLock) {
6421            displayInfo.rotation = mRotation;
6422            displayInfo.logicalWidth = dw;
6423            displayInfo.logicalHeight = dh;
6424            displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity;
6425            displayInfo.appWidth = appWidth;
6426            displayInfo.appHeight = appHeight;
6427            displayInfo.getLogicalMetrics(mRealDisplayMetrics, null);
6428            displayInfo.getAppMetrics(mDisplayMetrics, null);
6429            mDisplayManagerService.setDisplayInfoOverrideFromWindowManager(
6430                    displayContent.getDisplayId(), displayInfo);
6431        }
6432        if (false) {
6433            Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight);
6434        }
6435
6436        final DisplayMetrics dm = mDisplayMetrics;
6437        mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm,
6438                mCompatDisplayMetrics);
6439
6440        if (config != null) {
6441            config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation)
6442                    / dm.density);
6443            config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation)
6444                    / dm.density);
6445            computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, dm.density, config);
6446
6447            config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale);
6448            config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale);
6449            config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh);
6450            config.densityDpi = displayContent.mBaseDisplayDensity;
6451
6452            // Update the configuration based on available input devices, lid switch,
6453            // and platform configuration.
6454            config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
6455            config.keyboard = Configuration.KEYBOARD_NOKEYS;
6456            config.navigation = Configuration.NAVIGATION_NONAV;
6457
6458            int keyboardPresence = 0;
6459            int navigationPresence = 0;
6460            final InputDevice[] devices = mInputManager.getInputDevices();
6461            final int len = devices.length;
6462            for (int i = 0; i < len; i++) {
6463                InputDevice device = devices[i];
6464                if (!device.isVirtual()) {
6465                    final int sources = device.getSources();
6466                    final int presenceFlag = device.isExternal() ?
6467                            WindowManagerPolicy.PRESENCE_EXTERNAL :
6468                                    WindowManagerPolicy.PRESENCE_INTERNAL;
6469
6470                    if (mIsTouchDevice) {
6471                        if ((sources & InputDevice.SOURCE_TOUCHSCREEN) ==
6472                                InputDevice.SOURCE_TOUCHSCREEN) {
6473                            config.touchscreen = Configuration.TOUCHSCREEN_FINGER;
6474                        }
6475                    } else {
6476                        config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
6477                    }
6478
6479                    if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) {
6480                        config.navigation = Configuration.NAVIGATION_TRACKBALL;
6481                        navigationPresence |= presenceFlag;
6482                    } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD
6483                            && config.navigation == Configuration.NAVIGATION_NONAV) {
6484                        config.navigation = Configuration.NAVIGATION_DPAD;
6485                        navigationPresence |= presenceFlag;
6486                    }
6487
6488                    if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {
6489                        config.keyboard = Configuration.KEYBOARD_QWERTY;
6490                        keyboardPresence |= presenceFlag;
6491                    }
6492                }
6493            }
6494
6495            // Determine whether a hard keyboard is available and enabled.
6496            boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS;
6497            if (hardKeyboardAvailable != mHardKeyboardAvailable) {
6498                mHardKeyboardAvailable = hardKeyboardAvailable;
6499                mHardKeyboardEnabled = hardKeyboardAvailable;
6500                mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
6501                mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
6502            }
6503            if (!mHardKeyboardEnabled) {
6504                config.keyboard = Configuration.KEYBOARD_NOKEYS;
6505            }
6506
6507            // Let the policy update hidden states.
6508            config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
6509            config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
6510            config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO;
6511            mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence);
6512        }
6513
6514        return true;
6515    }
6516
6517    public boolean isHardKeyboardAvailable() {
6518        synchronized (mWindowMap) {
6519            return mHardKeyboardAvailable;
6520        }
6521    }
6522
6523    public boolean isHardKeyboardEnabled() {
6524        synchronized (mWindowMap) {
6525            return mHardKeyboardEnabled;
6526        }
6527    }
6528
6529    public void setHardKeyboardEnabled(boolean enabled) {
6530        synchronized (mWindowMap) {
6531            if (mHardKeyboardEnabled != enabled) {
6532                mHardKeyboardEnabled = enabled;
6533                mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
6534            }
6535        }
6536    }
6537
6538    public void setOnHardKeyboardStatusChangeListener(
6539            OnHardKeyboardStatusChangeListener listener) {
6540        synchronized (mWindowMap) {
6541            mHardKeyboardStatusChangeListener = listener;
6542        }
6543    }
6544
6545    void notifyHardKeyboardStatusChange() {
6546        final boolean available, enabled;
6547        final OnHardKeyboardStatusChangeListener listener;
6548        synchronized (mWindowMap) {
6549            listener = mHardKeyboardStatusChangeListener;
6550            available = mHardKeyboardAvailable;
6551            enabled = mHardKeyboardEnabled;
6552        }
6553        if (listener != null) {
6554            listener.onHardKeyboardStatusChange(available, enabled);
6555        }
6556    }
6557
6558    // -------------------------------------------------------------
6559    // Drag and drop
6560    // -------------------------------------------------------------
6561
6562    IBinder prepareDragSurface(IWindow window, SurfaceSession session,
6563            int flags, int width, int height, Surface outSurface) {
6564        if (DEBUG_DRAG) {
6565            Slog.d(TAG, "prepare drag surface: w=" + width + " h=" + height
6566                    + " flags=" + Integer.toHexString(flags) + " win=" + window
6567                    + " asbinder=" + window.asBinder());
6568        }
6569
6570        final int callerPid = Binder.getCallingPid();
6571        final long origId = Binder.clearCallingIdentity();
6572        IBinder token = null;
6573
6574        try {
6575            synchronized (mWindowMap) {
6576                try {
6577                    if (mDragState == null) {
6578                        // TODO(multi-display): support other displays
6579                        final DisplayContent displayContent = getDefaultDisplayContentLocked();
6580                        final Display display = displayContent.getDisplay();
6581                        SurfaceControl surface = new SurfaceControl(session, "drag surface",
6582                                width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
6583                        surface.setLayerStack(display.getLayerStack());
6584                        if (SHOW_TRANSACTIONS) Slog.i(TAG, "  DRAG "
6585                                + surface + ": CREATE");
6586                        outSurface.copyFrom(surface);
6587                        final IBinder winBinder = window.asBinder();
6588                        token = new Binder();
6589                        mDragState = new DragState(this, token, surface, /*flags*/ 0, winBinder);
6590                        token = mDragState.mToken = new Binder();
6591
6592                        // 5 second timeout for this window to actually begin the drag
6593                        mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder);
6594                        Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder);
6595                        mH.sendMessageDelayed(msg, 5000);
6596                    } else {
6597                        Slog.w(TAG, "Drag already in progress");
6598                    }
6599                } catch (SurfaceControl.OutOfResourcesException e) {
6600                    Slog.e(TAG, "Can't allocate drag surface w=" + width + " h=" + height, e);
6601                    if (mDragState != null) {
6602                        mDragState.reset();
6603                        mDragState = null;
6604                    }
6605                }
6606            }
6607        } finally {
6608            Binder.restoreCallingIdentity(origId);
6609        }
6610
6611        return token;
6612    }
6613
6614    // -------------------------------------------------------------
6615    // Input Events and Focus Management
6616    // -------------------------------------------------------------
6617
6618    final InputMonitor mInputMonitor = new InputMonitor(this);
6619    private boolean mEventDispatchingEnabled;
6620
6621    @Override
6622    public void pauseKeyDispatching(IBinder _token) {
6623        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
6624                "pauseKeyDispatching()")) {
6625            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
6626        }
6627
6628        synchronized (mWindowMap) {
6629            WindowToken token = mTokenMap.get(_token);
6630            if (token != null) {
6631                mInputMonitor.pauseDispatchingLw(token);
6632            }
6633        }
6634    }
6635
6636    @Override
6637    public void resumeKeyDispatching(IBinder _token) {
6638        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
6639                "resumeKeyDispatching()")) {
6640            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
6641        }
6642
6643        synchronized (mWindowMap) {
6644            WindowToken token = mTokenMap.get(_token);
6645            if (token != null) {
6646                mInputMonitor.resumeDispatchingLw(token);
6647            }
6648        }
6649    }
6650
6651    @Override
6652    public void setEventDispatching(boolean enabled) {
6653        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
6654                "setEventDispatching()")) {
6655            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
6656        }
6657
6658        synchronized (mWindowMap) {
6659            mEventDispatchingEnabled = enabled;
6660            if (mDisplayEnabled) {
6661                mInputMonitor.setEventDispatchingLw(enabled);
6662            }
6663            sendScreenStatusToClientsLocked();
6664        }
6665    }
6666
6667    @Override
6668    public IBinder getFocusedWindowToken() {
6669        if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO,
6670                "getFocusedWindowToken()")) {
6671            throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission.");
6672        }
6673        synchronized (mWindowMap) {
6674            WindowState windowState = getFocusedWindowLocked();
6675            if (windowState != null) {
6676                return windowState.mClient.asBinder();
6677            }
6678            return null;
6679        }
6680    }
6681
6682    private WindowState getFocusedWindow() {
6683        synchronized (mWindowMap) {
6684            return getFocusedWindowLocked();
6685        }
6686    }
6687
6688    private WindowState getFocusedWindowLocked() {
6689        return mCurrentFocus;
6690    }
6691
6692    public boolean detectSafeMode() {
6693        if (!mInputMonitor.waitForInputDevicesReady(
6694                INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) {
6695            Slog.w(TAG, "Devices still not ready after waiting "
6696                   + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS
6697                   + " milliseconds before attempting to detect safe mode.");
6698        }
6699
6700        int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
6701                KeyEvent.KEYCODE_MENU);
6702        int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S);
6703        int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD,
6704                KeyEvent.KEYCODE_DPAD_CENTER);
6705        int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL,
6706                InputManagerService.BTN_MOUSE);
6707        int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
6708                KeyEvent.KEYCODE_VOLUME_DOWN);
6709        mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0
6710                || volumeDownState > 0;
6711        try {
6712            if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0) {
6713                mSafeMode = true;
6714                SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, "");
6715            }
6716        } catch (IllegalArgumentException e) {
6717        }
6718        if (mSafeMode) {
6719            Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState
6720                    + " dpad=" + dpadState + " trackball=" + trackballState + ")");
6721        } else {
6722            Log.i(TAG, "SAFE MODE not enabled");
6723        }
6724        mPolicy.setSafeMode(mSafeMode);
6725        return mSafeMode;
6726    }
6727
6728    public void displayReady() {
6729        displayReady(Display.DEFAULT_DISPLAY);
6730
6731        synchronized(mWindowMap) {
6732            final DisplayContent displayContent = getDefaultDisplayContentLocked();
6733            readForcedDisplaySizeAndDensityLocked(displayContent);
6734
6735            mDisplayReady = true;
6736            mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
6737                    PackageManager.FEATURE_TOUCHSCREEN);
6738
6739            mPolicy.setInitialDisplaySize(displayContent.getDisplay(),
6740                    displayContent.mInitialDisplayWidth,
6741                    displayContent.mInitialDisplayHeight,
6742                    displayContent.mInitialDisplayDensity);
6743        }
6744
6745        try {
6746            mActivityManager.updateConfiguration(null);
6747        } catch (RemoteException e) {
6748        }
6749    }
6750
6751    private void displayReady(int displayId) {
6752        synchronized(mWindowMap) {
6753            final DisplayContent displayContent = getDisplayContentLocked(displayId);
6754            if (displayContent != null) {
6755                mAnimator.addDisplayLocked(displayId);
6756                synchronized(displayContent.mDisplaySizeLock) {
6757                    // Bootstrap the default logical display from the display manager.
6758                    final DisplayInfo displayInfo = displayContent.getDisplayInfo();
6759                    DisplayInfo newDisplayInfo = mDisplayManagerService.getDisplayInfo(displayId);
6760                    if (newDisplayInfo != null) {
6761                        displayInfo.copyFrom(newDisplayInfo);
6762                    }
6763                    displayContent.mInitialDisplayWidth = displayInfo.logicalWidth;
6764                    displayContent.mInitialDisplayHeight = displayInfo.logicalHeight;
6765                    displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi;
6766                    displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth;
6767                    displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight;
6768                    displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity;
6769                }
6770            }
6771        }
6772    }
6773
6774    public void systemReady() {
6775        mPolicy.systemReady();
6776    }
6777
6778    // TODO(multidisplay): Call isScreenOn for each display.
6779    private void sendScreenStatusToClientsLocked() {
6780        final boolean on = mPowerManager.isScreenOn();
6781        final AllWindowsIterator iterator = new AllWindowsIterator();
6782        while (iterator.hasNext()) {
6783            try {
6784                iterator.next().mClient.dispatchScreenState(on);
6785            } catch (RemoteException e) {
6786                // Ignored
6787            }
6788        }
6789    }
6790
6791    // -------------------------------------------------------------
6792    // Async Handler
6793    // -------------------------------------------------------------
6794
6795    final class H extends Handler {
6796        public static final int REPORT_FOCUS_CHANGE = 2;
6797        public static final int REPORT_LOSING_FOCUS = 3;
6798        public static final int DO_TRAVERSAL = 4;
6799        public static final int ADD_STARTING = 5;
6800        public static final int REMOVE_STARTING = 6;
6801        public static final int FINISHED_STARTING = 7;
6802        public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8;
6803        public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9;
6804        public static final int WINDOW_FREEZE_TIMEOUT = 11;
6805
6806        public static final int APP_TRANSITION_TIMEOUT = 13;
6807        public static final int PERSIST_ANIMATION_SCALE = 14;
6808        public static final int FORCE_GC = 15;
6809        public static final int ENABLE_SCREEN = 16;
6810        public static final int APP_FREEZE_TIMEOUT = 17;
6811        public static final int SEND_NEW_CONFIGURATION = 18;
6812        public static final int REPORT_WINDOWS_CHANGE = 19;
6813        public static final int DRAG_START_TIMEOUT = 20;
6814        public static final int DRAG_END_TIMEOUT = 21;
6815        public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22;
6816        public static final int BOOT_TIMEOUT = 23;
6817        public static final int WAITING_FOR_DRAWN_TIMEOUT = 24;
6818        public static final int SHOW_STRICT_MODE_VIOLATION = 25;
6819        public static final int DO_ANIMATION_CALLBACK = 26;
6820
6821        public static final int DO_DISPLAY_ADDED = 27;
6822        public static final int DO_DISPLAY_REMOVED = 28;
6823        public static final int DO_DISPLAY_CHANGED = 29;
6824
6825        public static final int CLIENT_FREEZE_TIMEOUT = 30;
6826
6827        @Override
6828        public void handleMessage(Message msg) {
6829            if (DEBUG_WINDOW_TRACE) {
6830                Slog.v(TAG, "handleMessage: entry what=" + msg.what);
6831            }
6832            switch (msg.what) {
6833                case REPORT_FOCUS_CHANGE: {
6834                    WindowState lastFocus;
6835                    WindowState newFocus;
6836
6837                    synchronized(mWindowMap) {
6838                        lastFocus = mLastFocus;
6839                        newFocus = mCurrentFocus;
6840                        if (lastFocus == newFocus) {
6841                            // Focus is not changing, so nothing to do.
6842                            return;
6843                        }
6844                        mLastFocus = newFocus;
6845                        //Slog.i(TAG, "Focus moving from " + lastFocus
6846                        //        + " to " + newFocus);
6847                        if (newFocus != null && lastFocus != null
6848                                && !newFocus.isDisplayedLw()) {
6849                            //Slog.i(TAG, "Delaying loss of focus...");
6850                            mLosingFocus.add(lastFocus);
6851                            lastFocus = null;
6852                        }
6853                    }
6854
6855                    if (lastFocus != newFocus) {
6856                        //System.out.println("Changing focus from " + lastFocus
6857                        //                   + " to " + newFocus);
6858                        if (newFocus != null) {
6859                            //Slog.i(TAG, "Gaining focus: " + newFocus);
6860                            newFocus.reportFocusChangedSerialized(true, mInTouchMode);
6861                            notifyFocusChanged();
6862                        }
6863
6864                        if (lastFocus != null) {
6865                            //Slog.i(TAG, "Losing focus: " + lastFocus);
6866                            lastFocus.reportFocusChangedSerialized(false, mInTouchMode);
6867                        }
6868                    }
6869                } break;
6870
6871                case REPORT_LOSING_FOCUS: {
6872                    ArrayList<WindowState> losers;
6873
6874                    synchronized(mWindowMap) {
6875                        losers = mLosingFocus;
6876                        mLosingFocus = new ArrayList<WindowState>();
6877                    }
6878
6879                    final int N = losers.size();
6880                    for (int i=0; i<N; i++) {
6881                        //Slog.i(TAG, "Losing delayed focus: " + losers.get(i));
6882                        losers.get(i).reportFocusChangedSerialized(false, mInTouchMode);
6883                    }
6884                } break;
6885
6886                case DO_TRAVERSAL: {
6887                    synchronized(mWindowMap) {
6888                        mTraversalScheduled = false;
6889                        performLayoutAndPlaceSurfacesLocked();
6890                    }
6891                } break;
6892
6893                case ADD_STARTING: {
6894                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
6895                    final StartingData sd = wtoken.startingData;
6896
6897                    if (sd == null) {
6898                        // Animation has been canceled... do nothing.
6899                        return;
6900                    }
6901
6902                    if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting "
6903                            + wtoken + ": pkg=" + sd.pkg);
6904
6905                    View view = null;
6906                    try {
6907                        view = mPolicy.addStartingWindow(
6908                            wtoken.token, sd.pkg, sd.theme, sd.compatInfo,
6909                            sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.windowFlags);
6910                    } catch (Exception e) {
6911                        Slog.w(TAG, "Exception when adding starting window", e);
6912                    }
6913
6914                    if (view != null) {
6915                        boolean abort = false;
6916
6917                        synchronized(mWindowMap) {
6918                            if (wtoken.removed || wtoken.startingData == null) {
6919                                // If the window was successfully added, then
6920                                // we need to remove it.
6921                                if (wtoken.startingWindow != null) {
6922                                    if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
6923                                            "Aborted starting " + wtoken
6924                                            + ": removed=" + wtoken.removed
6925                                            + " startingData=" + wtoken.startingData);
6926                                    wtoken.startingWindow = null;
6927                                    wtoken.startingData = null;
6928                                    abort = true;
6929                                }
6930                            } else {
6931                                wtoken.startingView = view;
6932                            }
6933                            if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG,
6934                                    "Added starting " + wtoken
6935                                    + ": startingWindow="
6936                                    + wtoken.startingWindow + " startingView="
6937                                    + wtoken.startingView);
6938                        }
6939
6940                        if (abort) {
6941                            try {
6942                                mPolicy.removeStartingWindow(wtoken.token, view);
6943                            } catch (Exception e) {
6944                                Slog.w(TAG, "Exception when removing starting window", e);
6945                            }
6946                        }
6947                    }
6948                } break;
6949
6950                case REMOVE_STARTING: {
6951                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
6952                    IBinder token = null;
6953                    View view = null;
6954                    synchronized (mWindowMap) {
6955                        if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting "
6956                                + wtoken + ": startingWindow="
6957                                + wtoken.startingWindow + " startingView="
6958                                + wtoken.startingView);
6959                        if (wtoken.startingWindow != null) {
6960                            view = wtoken.startingView;
6961                            token = wtoken.token;
6962                            wtoken.startingData = null;
6963                            wtoken.startingView = null;
6964                            wtoken.startingWindow = null;
6965                            wtoken.startingDisplayed = false;
6966                        }
6967                    }
6968                    if (view != null) {
6969                        try {
6970                            mPolicy.removeStartingWindow(token, view);
6971                        } catch (Exception e) {
6972                            Slog.w(TAG, "Exception when removing starting window", e);
6973                        }
6974                    }
6975                } break;
6976
6977                case FINISHED_STARTING: {
6978                    IBinder token = null;
6979                    View view = null;
6980                    while (true) {
6981                        synchronized (mWindowMap) {
6982                            final int N = mFinishedStarting.size();
6983                            if (N <= 0) {
6984                                break;
6985                            }
6986                            AppWindowToken wtoken = mFinishedStarting.remove(N-1);
6987
6988                            if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
6989                                    "Finished starting " + wtoken
6990                                    + ": startingWindow=" + wtoken.startingWindow
6991                                    + " startingView=" + wtoken.startingView);
6992
6993                            if (wtoken.startingWindow == null) {
6994                                continue;
6995                            }
6996
6997                            view = wtoken.startingView;
6998                            token = wtoken.token;
6999                            wtoken.startingData = null;
7000                            wtoken.startingView = null;
7001                            wtoken.startingWindow = null;
7002                            wtoken.startingDisplayed = false;
7003                        }
7004
7005                        try {
7006                            mPolicy.removeStartingWindow(token, view);
7007                        } catch (Exception e) {
7008                            Slog.w(TAG, "Exception when removing starting window", e);
7009                        }
7010                    }
7011                } break;
7012
7013                case REPORT_APPLICATION_TOKEN_DRAWN: {
7014                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7015
7016                    try {
7017                        if (DEBUG_VISIBILITY) Slog.v(
7018                                TAG, "Reporting drawn in " + wtoken);
7019                        wtoken.appToken.windowsDrawn();
7020                    } catch (RemoteException ex) {
7021                    }
7022                } break;
7023
7024                case REPORT_APPLICATION_TOKEN_WINDOWS: {
7025                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7026
7027                    boolean nowVisible = msg.arg1 != 0;
7028                    boolean nowGone = msg.arg2 != 0;
7029
7030                    try {
7031                        if (DEBUG_VISIBILITY) Slog.v(
7032                                TAG, "Reporting visible in " + wtoken
7033                                + " visible=" + nowVisible
7034                                + " gone=" + nowGone);
7035                        if (nowVisible) {
7036                            wtoken.appToken.windowsVisible();
7037                        } else {
7038                            wtoken.appToken.windowsGone();
7039                        }
7040                    } catch (RemoteException ex) {
7041                    }
7042                } break;
7043
7044                case WINDOW_FREEZE_TIMEOUT: {
7045                    // TODO(multidisplay): Can non-default displays rotate?
7046                    synchronized (mWindowMap) {
7047                        Slog.w(TAG, "Window freeze timeout expired.");
7048                        final WindowList windows = getDefaultWindowListLocked();
7049                        int i = windows.size();
7050                        while (i > 0) {
7051                            i--;
7052                            WindowState w = windows.get(i);
7053                            if (w.mOrientationChanging) {
7054                                w.mOrientationChanging = false;
7055                                w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
7056                                        - mDisplayFreezeTime);
7057                                Slog.w(TAG, "Force clearing orientation change: " + w);
7058                            }
7059                        }
7060                        performLayoutAndPlaceSurfacesLocked();
7061                    }
7062                    break;
7063                }
7064
7065                case APP_TRANSITION_TIMEOUT: {
7066                    synchronized (mWindowMap) {
7067                        if (mAppTransition.isTransitionSet()) {
7068                            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** APP TRANSITION TIMEOUT");
7069                            mAppTransition.setTimeout();
7070                            mAnimatingAppTokens.clear();
7071                            mAnimatingAppTokens.addAll(mAppTokens);
7072                            performLayoutAndPlaceSurfacesLocked();
7073                        }
7074                    }
7075                    break;
7076                }
7077
7078                case PERSIST_ANIMATION_SCALE: {
7079                    Settings.Global.putFloat(mContext.getContentResolver(),
7080                            Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
7081                    Settings.Global.putFloat(mContext.getContentResolver(),
7082                            Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
7083                    Settings.Global.putFloat(mContext.getContentResolver(),
7084                            Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScale);
7085                    break;
7086                }
7087
7088                case FORCE_GC: {
7089                    synchronized (mWindowMap) {
7090                        // Since we're holding both mWindowMap and mAnimator we don't need to
7091                        // hold mAnimator.mLayoutToAnim.
7092                        if (mAnimator.mAnimating || mAnimationScheduled) {
7093                            // If we are animating, don't do the gc now but
7094                            // delay a bit so we don't interrupt the animation.
7095                            sendEmptyMessageDelayed(H.FORCE_GC, 2000);
7096                            return;
7097                        }
7098                        // If we are currently rotating the display, it will
7099                        // schedule a new message when done.
7100                        if (mDisplayFrozen) {
7101                            return;
7102                        }
7103                    }
7104                    Runtime.getRuntime().gc();
7105                    break;
7106                }
7107
7108                case ENABLE_SCREEN: {
7109                    performEnableScreen();
7110                    break;
7111                }
7112
7113                case APP_FREEZE_TIMEOUT: {
7114                    synchronized (mWindowMap) {
7115                        Slog.w(TAG, "App freeze timeout expired.");
7116                        int i = mAppTokens.size();
7117                        while (i > 0) {
7118                            i--;
7119                            AppWindowToken tok = mAppTokens.get(i);
7120                            if (tok.mAppAnimator.freezingScreen) {
7121                                Slog.w(TAG, "Force clearing freeze: " + tok);
7122                                unsetAppFreezingScreenLocked(tok, true, true);
7123                            }
7124                        }
7125                    }
7126                    break;
7127                }
7128
7129                case CLIENT_FREEZE_TIMEOUT: {
7130                    synchronized (mWindowMap) {
7131                        if (mClientFreezingScreen) {
7132                            mClientFreezingScreen = false;
7133                            mLastFinishedFreezeSource = "client-timeout";
7134                            stopFreezingDisplayLocked();
7135                        }
7136                    }
7137                    break;
7138                }
7139
7140                case SEND_NEW_CONFIGURATION: {
7141                    removeMessages(SEND_NEW_CONFIGURATION);
7142                    sendNewConfiguration();
7143                    break;
7144                }
7145
7146                case REPORT_WINDOWS_CHANGE: {
7147                    if (mWindowsChanged) {
7148                        synchronized (mWindowMap) {
7149                            mWindowsChanged = false;
7150                        }
7151                        notifyWindowsChanged();
7152                    }
7153                    break;
7154                }
7155
7156                case DRAG_START_TIMEOUT: {
7157                    IBinder win = (IBinder)msg.obj;
7158                    if (DEBUG_DRAG) {
7159                        Slog.w(TAG, "Timeout starting drag by win " + win);
7160                    }
7161                    synchronized (mWindowMap) {
7162                        // !!! TODO: ANR the app that has failed to start the drag in time
7163                        if (mDragState != null) {
7164                            mDragState.unregister();
7165                            mInputMonitor.updateInputWindowsLw(true /*force*/);
7166                            mDragState.reset();
7167                            mDragState = null;
7168                        }
7169                    }
7170                    break;
7171                }
7172
7173                case DRAG_END_TIMEOUT: {
7174                    IBinder win = (IBinder)msg.obj;
7175                    if (DEBUG_DRAG) {
7176                        Slog.w(TAG, "Timeout ending drag to win " + win);
7177                    }
7178                    synchronized (mWindowMap) {
7179                        // !!! TODO: ANR the drag-receiving app
7180                        if (mDragState != null) {
7181                            mDragState.mDragResult = false;
7182                            mDragState.endDragLw();
7183                        }
7184                    }
7185                    break;
7186                }
7187
7188                case REPORT_HARD_KEYBOARD_STATUS_CHANGE: {
7189                    notifyHardKeyboardStatusChange();
7190                    break;
7191                }
7192
7193                case BOOT_TIMEOUT: {
7194                    performBootTimeout();
7195                    break;
7196                }
7197
7198                case WAITING_FOR_DRAWN_TIMEOUT: {
7199                    Pair<WindowState, IRemoteCallback> pair;
7200                    synchronized (mWindowMap) {
7201                        pair = (Pair<WindowState, IRemoteCallback>)msg.obj;
7202                        Slog.w(TAG, "Timeout waiting for drawn: " + pair.first);
7203                        if (!mWaitingForDrawn.remove(pair)) {
7204                            return;
7205                        }
7206                    }
7207                    try {
7208                        pair.second.sendResult(null);
7209                    } catch (RemoteException e) {
7210                    }
7211                    break;
7212                }
7213
7214                case SHOW_STRICT_MODE_VIOLATION: {
7215                    showStrictModeViolation(msg.arg1, msg.arg2);
7216                    break;
7217                }
7218
7219                case DO_ANIMATION_CALLBACK: {
7220                    try {
7221                        ((IRemoteCallback)msg.obj).sendResult(null);
7222                    } catch (RemoteException e) {
7223                    }
7224                    break;
7225                }
7226
7227                case DO_DISPLAY_ADDED:
7228                    synchronized (mWindowMap) {
7229                        handleDisplayAddedLocked(msg.arg1);
7230                    }
7231                    break;
7232
7233                case DO_DISPLAY_REMOVED:
7234                    synchronized (mWindowMap) {
7235                        handleDisplayRemovedLocked(msg.arg1);
7236                    }
7237                    break;
7238
7239                case DO_DISPLAY_CHANGED:
7240                    synchronized (mWindowMap) {
7241                        handleDisplayChangedLocked(msg.arg1);
7242                    }
7243                    break;
7244            }
7245            if (DEBUG_WINDOW_TRACE) {
7246                Slog.v(TAG, "handleMessage: exit");
7247            }
7248        }
7249    }
7250
7251    // -------------------------------------------------------------
7252    // IWindowManager API
7253    // -------------------------------------------------------------
7254
7255    @Override
7256    public IWindowSession openSession(IInputMethodClient client,
7257            IInputContext inputContext) {
7258        if (client == null) throw new IllegalArgumentException("null client");
7259        if (inputContext == null) throw new IllegalArgumentException("null inputContext");
7260        Session session = new Session(this, client, inputContext);
7261        return session;
7262    }
7263
7264    @Override
7265    public boolean inputMethodClientHasFocus(IInputMethodClient client) {
7266        synchronized (mWindowMap) {
7267            // The focus for the client is the window immediately below
7268            // where we would place the input method window.
7269            int idx = findDesiredInputMethodWindowIndexLocked(false);
7270            if (idx > 0) {
7271                // TODO(multidisplay): IMEs are only supported on the default display.
7272                WindowState imFocus = getDefaultWindowListLocked().get(idx-1);
7273                if (DEBUG_INPUT_METHOD) {
7274                    Slog.i(TAG, "Desired input method target: " + imFocus);
7275                    Slog.i(TAG, "Current focus: " + mCurrentFocus);
7276                    Slog.i(TAG, "Last focus: " + mLastFocus);
7277                }
7278                if (imFocus != null) {
7279                    // This may be a starting window, in which case we still want
7280                    // to count it as okay.
7281                    if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING
7282                            && imFocus.mAppToken != null) {
7283                        // The client has definitely started, so it really should
7284                        // have a window in this app token.  Let's look for it.
7285                        for (int i=0; i<imFocus.mAppToken.windows.size(); i++) {
7286                            WindowState w = imFocus.mAppToken.windows.get(i);
7287                            if (w != imFocus) {
7288                                Log.i(TAG, "Switching to real app window: " + w);
7289                                imFocus = w;
7290                                break;
7291                            }
7292                        }
7293                    }
7294                    if (DEBUG_INPUT_METHOD) {
7295                        Slog.i(TAG, "IM target client: " + imFocus.mSession.mClient);
7296                        if (imFocus.mSession.mClient != null) {
7297                            Slog.i(TAG, "IM target client binder: "
7298                                    + imFocus.mSession.mClient.asBinder());
7299                            Slog.i(TAG, "Requesting client binder: " + client.asBinder());
7300                        }
7301                    }
7302                    if (imFocus.mSession.mClient != null &&
7303                            imFocus.mSession.mClient.asBinder() == client.asBinder()) {
7304                        return true;
7305                    }
7306                }
7307            }
7308
7309            // Okay, how about this...  what is the current focus?
7310            // It seems in some cases we may not have moved the IM
7311            // target window, such as when it was in a pop-up window,
7312            // so let's also look at the current focus.  (An example:
7313            // go to Gmail, start searching so the keyboard goes up,
7314            // press home.  Sometimes the IME won't go down.)
7315            // Would be nice to fix this more correctly, but it's
7316            // way at the end of a release, and this should be good enough.
7317            if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null
7318                    && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) {
7319                return true;
7320            }
7321        }
7322        return false;
7323    }
7324
7325    @Override
7326    public void getInitialDisplaySize(int displayId, Point size) {
7327        synchronized (mWindowMap) {
7328            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7329            if (displayContent != null) {
7330                synchronized(displayContent.mDisplaySizeLock) {
7331                    size.x = displayContent.mInitialDisplayWidth;
7332                    size.y = displayContent.mInitialDisplayHeight;
7333                }
7334            }
7335        }
7336    }
7337
7338    @Override
7339    public void getBaseDisplaySize(int displayId, Point size) {
7340        synchronized (mWindowMap) {
7341            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7342            if (displayContent != null) {
7343                synchronized(displayContent.mDisplaySizeLock) {
7344                    size.x = displayContent.mBaseDisplayWidth;
7345                    size.y = displayContent.mBaseDisplayHeight;
7346                }
7347            }
7348        }
7349    }
7350
7351    @Override
7352    public void setForcedDisplaySize(int displayId, int width, int height) {
7353        if (mContext.checkCallingOrSelfPermission(
7354                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7355                PackageManager.PERMISSION_GRANTED) {
7356            throw new SecurityException("Must hold permission " +
7357                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
7358        }
7359        if (displayId != Display.DEFAULT_DISPLAY) {
7360            throw new IllegalArgumentException("Can only set the default display");
7361        }
7362        synchronized(mWindowMap) {
7363            // Set some sort of reasonable bounds on the size of the display that we
7364            // will try to emulate.
7365            final int MIN_WIDTH = 200;
7366            final int MIN_HEIGHT = 200;
7367            final int MAX_SCALE = 2;
7368            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7369            if (displayContent != null) {
7370                width = Math.min(Math.max(width, MIN_WIDTH),
7371                        displayContent.mInitialDisplayWidth * MAX_SCALE);
7372                height = Math.min(Math.max(height, MIN_HEIGHT),
7373                        displayContent.mInitialDisplayHeight * MAX_SCALE);
7374                setForcedDisplaySizeLocked(displayContent, width, height);
7375                Settings.Global.putString(mContext.getContentResolver(),
7376                        Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height);
7377            }
7378        }
7379    }
7380
7381    private void readForcedDisplaySizeAndDensityLocked(final DisplayContent displayContent) {
7382        final String sizeStr = Settings.Global.getString(mContext.getContentResolver(),
7383                Settings.Global.DISPLAY_SIZE_FORCED);
7384        if (sizeStr != null && sizeStr.length() > 0) {
7385            final int pos = sizeStr.indexOf(',');
7386            if (pos > 0 && sizeStr.lastIndexOf(',') == pos) {
7387                int width, height;
7388                try {
7389                    width = Integer.parseInt(sizeStr.substring(0, pos));
7390                    height = Integer.parseInt(sizeStr.substring(pos+1));
7391                    synchronized(displayContent.mDisplaySizeLock) {
7392                        if (displayContent.mBaseDisplayWidth != width
7393                                || displayContent.mBaseDisplayHeight != height) {
7394                            Slog.i(TAG, "FORCED DISPLAY SIZE: " + width + "x" + height);
7395                            displayContent.mBaseDisplayWidth = width;
7396                            displayContent.mBaseDisplayHeight = height;
7397                        }
7398                    }
7399                } catch (NumberFormatException ex) {
7400                }
7401            }
7402        }
7403        final String densityStr = Settings.Global.getString(mContext.getContentResolver(),
7404                Settings.Global.DISPLAY_DENSITY_FORCED);
7405        if (densityStr != null && densityStr.length() > 0) {
7406            int density;
7407            try {
7408                density = Integer.parseInt(densityStr);
7409                synchronized(displayContent.mDisplaySizeLock) {
7410                    if (displayContent.mBaseDisplayDensity != density) {
7411                        Slog.i(TAG, "FORCED DISPLAY DENSITY: " + density);
7412                        displayContent.mBaseDisplayDensity = density;
7413                    }
7414                }
7415            } catch (NumberFormatException ex) {
7416            }
7417        }
7418    }
7419
7420    // displayContent must not be null
7421    private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {
7422        Slog.i(TAG, "Using new display size: " + width + "x" + height);
7423
7424        synchronized(displayContent.mDisplaySizeLock) {
7425            displayContent.mBaseDisplayWidth = width;
7426            displayContent.mBaseDisplayHeight = height;
7427        }
7428        reconfigureDisplayLocked(displayContent);
7429    }
7430
7431    @Override
7432    public void clearForcedDisplaySize(int displayId) {
7433        if (mContext.checkCallingOrSelfPermission(
7434                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7435                PackageManager.PERMISSION_GRANTED) {
7436            throw new SecurityException("Must hold permission " +
7437                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
7438        }
7439        if (displayId != Display.DEFAULT_DISPLAY) {
7440            throw new IllegalArgumentException("Can only set the default display");
7441        }
7442        synchronized(mWindowMap) {
7443            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7444            if (displayContent != null) {
7445                setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
7446                        displayContent.mInitialDisplayHeight);
7447                Settings.Global.putString(mContext.getContentResolver(),
7448                        Settings.Global.DISPLAY_SIZE_FORCED, "");
7449            }
7450        }
7451    }
7452
7453    @Override
7454    public int getInitialDisplayDensity(int displayId) {
7455        synchronized (mWindowMap) {
7456            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7457            if (displayContent != null) {
7458                synchronized(displayContent.mDisplaySizeLock) {
7459                    return displayContent.mInitialDisplayDensity;
7460                }
7461            }
7462        }
7463        return -1;
7464    }
7465
7466    @Override
7467    public int getBaseDisplayDensity(int displayId) {
7468        synchronized (mWindowMap) {
7469            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7470            if (displayContent != null) {
7471                synchronized(displayContent.mDisplaySizeLock) {
7472                    return displayContent.mBaseDisplayDensity;
7473                }
7474            }
7475        }
7476        return -1;
7477    }
7478
7479    @Override
7480    public void setForcedDisplayDensity(int displayId, int density) {
7481        if (mContext.checkCallingOrSelfPermission(
7482                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7483                PackageManager.PERMISSION_GRANTED) {
7484            throw new SecurityException("Must hold permission " +
7485                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
7486        }
7487        if (displayId != Display.DEFAULT_DISPLAY) {
7488            throw new IllegalArgumentException("Can only set the default display");
7489        }
7490        synchronized(mWindowMap) {
7491            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7492            if (displayContent != null) {
7493                setForcedDisplayDensityLocked(displayContent, density);
7494                Settings.Global.putString(mContext.getContentResolver(),
7495                        Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density));
7496            }
7497        }
7498    }
7499
7500    // displayContent must not be null
7501    private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) {
7502        Slog.i(TAG, "Using new display density: " + density);
7503
7504        synchronized(displayContent.mDisplaySizeLock) {
7505            displayContent.mBaseDisplayDensity = density;
7506        }
7507        reconfigureDisplayLocked(displayContent);
7508    }
7509
7510    @Override
7511    public void clearForcedDisplayDensity(int displayId) {
7512        if (mContext.checkCallingOrSelfPermission(
7513                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7514                PackageManager.PERMISSION_GRANTED) {
7515            throw new SecurityException("Must hold permission " +
7516                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
7517        }
7518        if (displayId != Display.DEFAULT_DISPLAY) {
7519            throw new IllegalArgumentException("Can only set the default display");
7520        }
7521        synchronized(mWindowMap) {
7522            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7523            if (displayContent != null) {
7524                setForcedDisplayDensityLocked(displayContent, displayContent.mInitialDisplayDensity);
7525                Settings.Global.putString(mContext.getContentResolver(),
7526                        Settings.Global.DISPLAY_DENSITY_FORCED, "");
7527            }
7528        }
7529    }
7530
7531    // displayContent must not be null
7532    private void reconfigureDisplayLocked(DisplayContent displayContent) {
7533        // TODO: Multidisplay: for now only use with default display.
7534        mPolicy.setInitialDisplaySize(displayContent.getDisplay(),
7535                displayContent.mBaseDisplayWidth,
7536                displayContent.mBaseDisplayHeight,
7537                displayContent.mBaseDisplayDensity);
7538
7539        displayContent.layoutNeeded = true;
7540
7541        boolean configChanged = updateOrientationFromAppTokensLocked(false);
7542        mTempConfiguration.setToDefaults();
7543        mTempConfiguration.fontScale = mCurConfiguration.fontScale;
7544        if (computeScreenConfigurationLocked(mTempConfiguration)) {
7545            if (mCurConfiguration.diff(mTempConfiguration) != 0) {
7546                configChanged = true;
7547            }
7548        }
7549
7550        if (configChanged) {
7551            mWaitingForConfig = true;
7552            startFreezingDisplayLocked(false, 0, 0);
7553            mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
7554        }
7555
7556        performLayoutAndPlaceSurfacesLocked();
7557    }
7558
7559    @Override
7560    public void setOverscan(int displayId, int left, int top, int right, int bottom) {
7561        if (mContext.checkCallingOrSelfPermission(
7562                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7563                PackageManager.PERMISSION_GRANTED) {
7564            throw new SecurityException("Must hold permission " +
7565                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
7566        }
7567        synchronized(mWindowMap) {
7568            DisplayContent displayContent = getDisplayContentLocked(displayId);
7569            if (displayContent != null) {
7570                mDisplayManagerService.setOverscan(displayId, left, top, right, bottom);
7571                final DisplayInfo displayInfo = displayContent.getDisplayInfo();
7572                synchronized(displayContent.mDisplaySizeLock) {
7573                    displayInfo.overscanLeft = left;
7574                    displayInfo.overscanTop = top;
7575                    displayInfo.overscanRight = right;
7576                    displayInfo.overscanBottom = bottom;
7577                }
7578                mPolicy.setDisplayOverscan(displayContent.getDisplay(), left, top, right, bottom);
7579                displayContent.layoutNeeded = true;
7580                mDisplaySettings.setOverscanLocked(displayInfo.name, left, top, right, bottom);
7581                mDisplaySettings.writeSettingsLocked();
7582                performLayoutAndPlaceSurfacesLocked();
7583            }
7584        }
7585    }
7586
7587    @Override
7588    public boolean hasSystemNavBar() {
7589        return mPolicy.hasSystemNavBar();
7590    }
7591
7592    // -------------------------------------------------------------
7593    // Internals
7594    // -------------------------------------------------------------
7595
7596    final WindowState windowForClientLocked(Session session, IWindow client,
7597            boolean throwOnError) {
7598        return windowForClientLocked(session, client.asBinder(), throwOnError);
7599    }
7600
7601    final WindowState windowForClientLocked(Session session, IBinder client,
7602            boolean throwOnError) {
7603        WindowState win = mWindowMap.get(client);
7604        if (localLOGV) Slog.v(
7605            TAG, "Looking up client " + client + ": " + win);
7606        if (win == null) {
7607            RuntimeException ex = new IllegalArgumentException(
7608                    "Requested window " + client + " does not exist");
7609            if (throwOnError) {
7610                throw ex;
7611            }
7612            Slog.w(TAG, "Failed looking up window", ex);
7613            return null;
7614        }
7615        if (session != null && win.mSession != session) {
7616            RuntimeException ex = new IllegalArgumentException(
7617                    "Requested window " + client + " is in session " +
7618                    win.mSession + ", not " + session);
7619            if (throwOnError) {
7620                throw ex;
7621            }
7622            Slog.w(TAG, "Failed looking up window", ex);
7623            return null;
7624        }
7625
7626        return win;
7627    }
7628
7629    final void rebuildAppWindowListLocked() {
7630        DisplayContentsIterator iterator = new DisplayContentsIterator();
7631        while (iterator.hasNext()) {
7632            rebuildAppWindowListLocked(iterator.next());
7633        }
7634    }
7635
7636    private void rebuildAppWindowListLocked(final DisplayContent displayContent) {
7637        final WindowList windows = displayContent.getWindowList();
7638        int NW = windows.size();
7639        int i;
7640        int lastBelow = -1;
7641        int numRemoved = 0;
7642
7643        if (mRebuildTmp.length < NW) {
7644            mRebuildTmp = new WindowState[NW+10];
7645        }
7646
7647        // First remove all existing app windows.
7648        i=0;
7649        while (i < NW) {
7650            WindowState w = windows.get(i);
7651            if (w.mAppToken != null) {
7652                WindowState win = windows.remove(i);
7653                win.mRebuilding = true;
7654                mRebuildTmp[numRemoved] = win;
7655                mWindowsChanged = true;
7656                if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
7657                        "Rebuild removing window: " + win);
7658                NW--;
7659                numRemoved++;
7660                continue;
7661            } else if (lastBelow == i-1) {
7662                if (w.mAttrs.type == TYPE_WALLPAPER || w.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
7663                    lastBelow = i;
7664                }
7665            }
7666            i++;
7667        }
7668
7669        // Keep whatever windows were below the app windows still below,
7670        // by skipping them.
7671        lastBelow++;
7672        i = lastBelow;
7673
7674        // First add all of the exiting app tokens...  these are no longer
7675        // in the main app list, but still have windows shown.  We put them
7676        // in the back because now that the animation is over we no longer
7677        // will care about them.
7678        int NT = mExitingAppTokens.size();
7679        for (int j=0; j<NT; j++) {
7680            i = reAddAppWindowsLocked(displayContent, i, mExitingAppTokens.get(j));
7681        }
7682
7683        // And add in the still active app tokens in Z order.
7684        NT = mAnimatingAppTokens.size();
7685        for (int j=0; j<NT; j++) {
7686            i = reAddAppWindowsLocked(displayContent, i, mAnimatingAppTokens.get(j));
7687        }
7688
7689        i -= lastBelow;
7690        if (i != numRemoved) {
7691            Slog.w(TAG, "Rebuild removed " + numRemoved
7692                    + " windows but added " + i);
7693            for (i=0; i<numRemoved; i++) {
7694                WindowState ws = mRebuildTmp[i];
7695                if (ws.mRebuilding) {
7696                    StringWriter sw = new StringWriter();
7697                    PrintWriter pw = new PrintWriter(sw);
7698                    ws.dump(pw, "", true);
7699                    pw.flush();
7700                    Slog.w(TAG, "This window was lost: " + ws);
7701                    Slog.w(TAG, sw.toString());
7702                    ws.mWinAnimator.destroySurfaceLocked();
7703                }
7704            }
7705            Slog.w(TAG, "Current app token list:");
7706            dumpAnimatingAppTokensLocked();
7707            Slog.w(TAG, "Final window list:");
7708            dumpWindowsLocked();
7709        }
7710    }
7711
7712    private final void assignLayersLocked(WindowList windows) {
7713        int N = windows.size();
7714        int curBaseLayer = 0;
7715        int curLayer = 0;
7716        int i;
7717
7718        if (DEBUG_LAYERS) {
7719            RuntimeException here = new RuntimeException("here");
7720            here.fillInStackTrace();
7721            Slog.v(TAG, "Assigning layers", here);
7722        }
7723
7724        boolean anyLayerChanged = false;
7725
7726        for (i=0; i<N; i++) {
7727            final WindowState w = windows.get(i);
7728            final WindowStateAnimator winAnimator = w.mWinAnimator;
7729            boolean layerChanged = false;
7730            int oldLayer = w.mLayer;
7731            if (w.mBaseLayer == curBaseLayer || w.mIsImWindow
7732                    || (i > 0 && w.mIsWallpaper)) {
7733                curLayer += WINDOW_LAYER_MULTIPLIER;
7734                w.mLayer = curLayer;
7735            } else {
7736                curBaseLayer = curLayer = w.mBaseLayer;
7737                w.mLayer = curLayer;
7738            }
7739            if (w.mLayer != oldLayer) {
7740                layerChanged = true;
7741                anyLayerChanged = true;
7742            }
7743            oldLayer = winAnimator.mAnimLayer;
7744            if (w.mTargetAppToken != null) {
7745                winAnimator.mAnimLayer =
7746                        w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment;
7747            } else if (w.mAppToken != null) {
7748                winAnimator.mAnimLayer =
7749                        w.mLayer + w.mAppToken.mAppAnimator.animLayerAdjustment;
7750            } else {
7751                winAnimator.mAnimLayer = w.mLayer;
7752            }
7753            if (w.mIsImWindow) {
7754                winAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment;
7755            } else if (w.mIsWallpaper) {
7756                winAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment;
7757            }
7758            if (winAnimator.mAnimLayer != oldLayer) {
7759                layerChanged = true;
7760                anyLayerChanged = true;
7761            }
7762            if (layerChanged && mAnimator.isDimmingLocked(winAnimator)) {
7763                // Force an animation pass just to update the mDimAnimator layer.
7764                scheduleAnimationLocked();
7765            }
7766            if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": "
7767                    + "mBase=" + w.mBaseLayer
7768                    + " mLayer=" + w.mLayer
7769                    + (w.mAppToken == null ?
7770                            "" : " mAppLayer=" + w.mAppToken.mAppAnimator.animLayerAdjustment)
7771                    + " =mAnimLayer=" + winAnimator.mAnimLayer);
7772            //System.out.println(
7773            //    "Assigned layer " + curLayer + " to " + w.mClient.asBinder());
7774        }
7775
7776        //TODO (multidisplay): Magnification is supported only for the default display.
7777        if (mDisplayMagnifier != null && anyLayerChanged
7778                && windows.get(windows.size() - 1).getDisplayId() == Display.DEFAULT_DISPLAY) {
7779            mDisplayMagnifier.onWindowLayersChangedLocked();
7780        }
7781    }
7782
7783    private final void performLayoutAndPlaceSurfacesLocked() {
7784        int loopCount = 6;
7785        do {
7786            mTraversalScheduled = false;
7787            performLayoutAndPlaceSurfacesLockedLoop();
7788            mH.removeMessages(H.DO_TRAVERSAL);
7789            loopCount--;
7790        } while (mTraversalScheduled && loopCount > 0);
7791        mInnerFields.mWallpaperActionPending = false;
7792    }
7793
7794    private boolean mInLayout = false;
7795    private final void performLayoutAndPlaceSurfacesLockedLoop() {
7796        if (mInLayout) {
7797            if (DEBUG) {
7798                throw new RuntimeException("Recursive call!");
7799            }
7800            Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers="
7801                    + Debug.getCallers(3));
7802            return;
7803        }
7804
7805        if (mWaitingForConfig) {
7806            // Our configuration has changed (most likely rotation), but we
7807            // don't yet have the complete configuration to report to
7808            // applications.  Don't do any window layout until we have it.
7809            return;
7810        }
7811
7812        if (!mDisplayReady) {
7813            // Not yet initialized, nothing to do.
7814            return;
7815        }
7816
7817        Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout");
7818        mInLayout = true;
7819        boolean recoveringMemory = false;
7820
7821        try {
7822            if (mForceRemoves != null) {
7823                recoveringMemory = true;
7824                // Wait a little bit for things to settle down, and off we go.
7825                for (int i=0; i<mForceRemoves.size(); i++) {
7826                    WindowState ws = mForceRemoves.get(i);
7827                    Slog.i(TAG, "Force removing: " + ws);
7828                    removeWindowInnerLocked(ws.mSession, ws);
7829                }
7830                mForceRemoves = null;
7831                Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");
7832                Object tmp = new Object();
7833                synchronized (tmp) {
7834                    try {
7835                        tmp.wait(250);
7836                    } catch (InterruptedException e) {
7837                    }
7838                }
7839            }
7840        } catch (RuntimeException e) {
7841            Log.wtf(TAG, "Unhandled exception while force removing for memory", e);
7842        }
7843
7844        try {
7845            performLayoutAndPlaceSurfacesLockedInner(recoveringMemory);
7846
7847            mInLayout = false;
7848
7849            if (needsLayout()) {
7850                if (++mLayoutRepeatCount < 6) {
7851                    requestTraversalLocked();
7852                } else {
7853                    Slog.e(TAG, "Performed 6 layouts in a row. Skipping");
7854                    mLayoutRepeatCount = 0;
7855                }
7856            } else {
7857                mLayoutRepeatCount = 0;
7858            }
7859
7860            if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) {
7861                mH.removeMessages(H.REPORT_WINDOWS_CHANGE);
7862                mH.sendEmptyMessage(H.REPORT_WINDOWS_CHANGE);
7863            }
7864        } catch (RuntimeException e) {
7865            mInLayout = false;
7866            Log.wtf(TAG, "Unhandled exception while laying out windows", e);
7867        }
7868
7869        Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
7870    }
7871
7872    private final void performLayoutLockedInner(final DisplayContent displayContent,
7873                                    boolean initial, boolean updateInputWindows) {
7874        if (!displayContent.layoutNeeded) {
7875            return;
7876        }
7877        displayContent.layoutNeeded = false;
7878        WindowList windows = displayContent.getWindowList();
7879        boolean isDefaultDisplay = displayContent.isDefaultDisplay;
7880
7881        DisplayInfo displayInfo = displayContent.getDisplayInfo();
7882        final int dw = displayInfo.logicalWidth;
7883        final int dh = displayInfo.logicalHeight;
7884
7885        final int NFW = mFakeWindows.size();
7886        for (int i=0; i<NFW; i++) {
7887            mFakeWindows.get(i).layout(dw, dh);
7888        }
7889
7890        final int N = windows.size();
7891        int i;
7892
7893        if (DEBUG_LAYOUT) {
7894            Slog.v(TAG, "-------------------------------------");
7895            Slog.v(TAG, "performLayout: needed="
7896                    + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh);
7897        }
7898
7899        WindowStateAnimator universeBackground = null;
7900
7901        mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mRotation);
7902        if (isDefaultDisplay) {
7903            // Not needed on non-default displays.
7904            mSystemDecorLayer = mPolicy.getSystemDecorRectLw(mSystemDecorRect);
7905            mScreenRect.set(0, 0, dw, dh);
7906        }
7907
7908        int seq = mLayoutSeq+1;
7909        if (seq < 0) seq = 0;
7910        mLayoutSeq = seq;
7911
7912        boolean behindDream = false;
7913
7914        // First perform layout of any root windows (not attached
7915        // to another window).
7916        int topAttached = -1;
7917        for (i = N-1; i >= 0; i--) {
7918            final WindowState win = windows.get(i);
7919
7920            // Don't do layout of a window if it is not visible, or
7921            // soon won't be visible, to avoid wasting time and funky
7922            // changes while a window is animating away.
7923            final boolean gone = (behindDream && mPolicy.canBeForceHidden(win, win.mAttrs))
7924                    || win.isGoneForLayoutLw();
7925
7926            if (DEBUG_LAYOUT && !win.mLayoutAttached) {
7927                Slog.v(TAG, "1ST PASS " + win
7928                        + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame
7929                        + " mLayoutAttached=" + win.mLayoutAttached
7930                        + " screen changed=" + win.isConfigChanged());
7931                final AppWindowToken atoken = win.mAppToken;
7932                if (gone) Slog.v(TAG, "  GONE: mViewVisibility="
7933                        + win.mViewVisibility + " mRelayoutCalled="
7934                        + win.mRelayoutCalled + " hidden="
7935                        + win.mRootToken.hidden + " hiddenRequested="
7936                        + (atoken != null && atoken.hiddenRequested)
7937                        + " mAttachedHidden=" + win.mAttachedHidden);
7938                else Slog.v(TAG, "  VIS: mViewVisibility="
7939                        + win.mViewVisibility + " mRelayoutCalled="
7940                        + win.mRelayoutCalled + " hidden="
7941                        + win.mRootToken.hidden + " hiddenRequested="
7942                        + (atoken != null && atoken.hiddenRequested)
7943                        + " mAttachedHidden=" + win.mAttachedHidden);
7944            }
7945
7946            // If this view is GONE, then skip it -- keep the current
7947            // frame, and let the caller know so they can ignore it
7948            // if they want.  (We do the normal layout for INVISIBLE
7949            // windows, since that means "perform layout as normal,
7950            // just don't display").
7951            if (!gone || !win.mHaveFrame || win.mLayoutNeeded
7952                    || (win.mAttrs.type == TYPE_KEYGUARD && win.isConfigChanged())
7953                    || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
7954                if (!win.mLayoutAttached) {
7955                    if (initial) {
7956                        //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
7957                        win.mContentChanged = false;
7958                    }
7959                    if (win.mAttrs.type == TYPE_DREAM) {
7960                        // Don't layout windows behind a dream, so that if it
7961                        // does stuff like hide the status bar we won't get a
7962                        // bad transition when it goes away.
7963                        behindDream = true;
7964                    }
7965                    win.mLayoutNeeded = false;
7966                    win.prelayout();
7967                    mPolicy.layoutWindowLw(win, win.mAttrs, null);
7968                    win.mLayoutSeq = seq;
7969                    if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame="
7970                            + win.mFrame + " mContainingFrame="
7971                            + win.mContainingFrame + " mDisplayFrame="
7972                            + win.mDisplayFrame);
7973                } else {
7974                    if (topAttached < 0) topAttached = i;
7975                }
7976            }
7977            if (win.mViewVisibility == View.VISIBLE
7978                    && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND
7979                    && universeBackground == null) {
7980                universeBackground = win.mWinAnimator;
7981            }
7982        }
7983
7984        if (mAnimator.mUniverseBackground  != universeBackground) {
7985            mFocusMayChange = true;
7986            mAnimator.mUniverseBackground = universeBackground;
7987        }
7988
7989        boolean attachedBehindDream = false;
7990
7991        // Now perform layout of attached windows, which usually
7992        // depend on the position of the window they are attached to.
7993        // XXX does not deal with windows that are attached to windows
7994        // that are themselves attached.
7995        for (i = topAttached; i >= 0; i--) {
7996            final WindowState win = windows.get(i);
7997
7998            if (win.mLayoutAttached) {
7999                if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win
8000                        + " mHaveFrame=" + win.mHaveFrame
8001                        + " mViewVisibility=" + win.mViewVisibility
8002                        + " mRelayoutCalled=" + win.mRelayoutCalled);
8003                // If this view is GONE, then skip it -- keep the current
8004                // frame, and let the caller know so they can ignore it
8005                // if they want.  (We do the normal layout for INVISIBLE
8006                // windows, since that means "perform layout as normal,
8007                // just don't display").
8008                if (attachedBehindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) {
8009                    continue;
8010                }
8011                if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled)
8012                        || !win.mHaveFrame || win.mLayoutNeeded) {
8013                    if (initial) {
8014                        //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
8015                        win.mContentChanged = false;
8016                    }
8017                    win.mLayoutNeeded = false;
8018                    win.prelayout();
8019                    mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow);
8020                    win.mLayoutSeq = seq;
8021                    if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame="
8022                            + win.mFrame + " mContainingFrame="
8023                            + win.mContainingFrame + " mDisplayFrame="
8024                            + win.mDisplayFrame);
8025                }
8026            } else if (win.mAttrs.type == TYPE_DREAM) {
8027                // Don't layout windows behind a dream, so that if it
8028                // does stuff like hide the status bar we won't get a
8029                // bad transition when it goes away.
8030                attachedBehindDream = behindDream;
8031            }
8032        }
8033
8034        // Window frames may have changed.  Tell the input dispatcher about it.
8035        mInputMonitor.setUpdateInputWindowsNeededLw();
8036        if (updateInputWindows) {
8037            mInputMonitor.updateInputWindowsLw(false /*force*/);
8038        }
8039
8040        mPolicy.finishLayoutLw();
8041    }
8042
8043    void makeWindowFreezingScreenIfNeededLocked(WindowState w) {
8044        // If the screen is currently frozen or off, then keep
8045        // it frozen/off until this window draws at its new
8046        // orientation.
8047        if (!okToDisplay()) {
8048            if (DEBUG_ORIENTATION) Slog.v(TAG,
8049                    "Changing surface while display frozen: " + w);
8050            w.mOrientationChanging = true;
8051            w.mLastFreezeDuration = 0;
8052            mInnerFields.mOrientationChangeComplete = false;
8053            if (!mWindowsFreezingScreen) {
8054                mWindowsFreezingScreen = true;
8055                // XXX should probably keep timeout from
8056                // when we first froze the display.
8057                mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
8058                mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT,
8059                        WINDOW_FREEZE_TIMEOUT_DURATION);
8060            }
8061        }
8062    }
8063
8064    /**
8065     * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
8066     * @param windows List of windows on default display.
8067     * @return bitmap indicating if another pass through layout must be made.
8068     */
8069    public int handleAppTransitionReadyLocked(WindowList windows) {
8070        int changes = 0;
8071        int i;
8072        int NN = mOpeningApps.size();
8073        boolean goodToGo = true;
8074        if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8075                "Checking " + NN + " opening apps (frozen="
8076                + mDisplayFrozen + " timeout="
8077                + mAppTransition.isTimeout() + ")...");
8078        if (!mDisplayFrozen && !mAppTransition.isTimeout()) {
8079            // If the display isn't frozen, wait to do anything until
8080            // all of the apps are ready.  Otherwise just go because
8081            // we'll unfreeze the display when everyone is ready.
8082            for (i=0; i<NN && goodToGo; i++) {
8083                AppWindowToken wtoken = mOpeningApps.get(i);
8084                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8085                        "Check opening app=" + wtoken + ": allDrawn="
8086                        + wtoken.allDrawn + " startingDisplayed="
8087                        + wtoken.startingDisplayed + " startingMoved="
8088                        + wtoken.startingMoved);
8089                if (!wtoken.allDrawn && !wtoken.startingDisplayed
8090                        && !wtoken.startingMoved) {
8091                    goodToGo = false;
8092                }
8093            }
8094        }
8095        if (goodToGo) {
8096            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO");
8097            int transit = mAppTransition.getAppTransition();
8098            if (mSkipAppTransitionAnimation) {
8099                transit = AppTransition.TRANSIT_UNSET;
8100            }
8101            mAppTransition.goodToGo();
8102            mStartingIconInTransition = false;
8103            mSkipAppTransitionAnimation = false;
8104
8105            mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
8106
8107            rebuildAppWindowListLocked();
8108
8109            // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper
8110            WindowState oldWallpaper =
8111                    mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating()
8112                        && !mWallpaperTarget.mWinAnimator.isDummyAnimation()
8113                    ? null : mWallpaperTarget;
8114
8115            mInnerFields.mWallpaperMayChange = false;
8116
8117            // The top-most window will supply the layout params,
8118            // and we will determine it below.
8119            LayoutParams animLp = null;
8120            int bestAnimLayer = -1;
8121            boolean fullscreenAnim = false;
8122
8123            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8124                    "New wallpaper target=" + mWallpaperTarget
8125                    + ", oldWallpaper=" + oldWallpaper
8126                    + ", lower target=" + mLowerWallpaperTarget
8127                    + ", upper target=" + mUpperWallpaperTarget);
8128
8129            boolean openingAppHasWallpaper = false;
8130            boolean closingAppHasWallpaper = false;
8131            final AppWindowToken lowerWallpaperAppToken;
8132            final AppWindowToken upperWallpaperAppToken;
8133            if (mLowerWallpaperTarget == null) {
8134                lowerWallpaperAppToken = upperWallpaperAppToken = null;
8135            } else {
8136                lowerWallpaperAppToken = mLowerWallpaperTarget.mAppToken;
8137                upperWallpaperAppToken = mUpperWallpaperTarget.mAppToken;
8138            }
8139
8140            // Do a first pass through the tokens for two
8141            // things:
8142            // (1) Determine if both the closing and opening
8143            // app token sets are wallpaper targets, in which
8144            // case special animations are needed
8145            // (since the wallpaper needs to stay static
8146            // behind them).
8147            // (2) Find the layout params of the top-most
8148            // application window in the tokens, which is
8149            // what will control the animation theme.
8150            final int NC = mClosingApps.size();
8151            NN = NC + mOpeningApps.size();
8152            for (i=0; i<NN; i++) {
8153                final AppWindowToken wtoken;
8154                if (i < NC) {
8155                    wtoken = mClosingApps.get(i);
8156                    if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
8157                        closingAppHasWallpaper = true;
8158                    }
8159                } else {
8160                    wtoken = mOpeningApps.get(i - NC);
8161                    if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
8162                        openingAppHasWallpaper = true;
8163                    }
8164                }
8165
8166                if (wtoken.appFullscreen) {
8167                    WindowState ws = wtoken.findMainWindow();
8168                    if (ws != null) {
8169                        animLp = ws.mAttrs;
8170                        bestAnimLayer = ws.mLayer;
8171                        fullscreenAnim = true;
8172                    }
8173                } else if (!fullscreenAnim) {
8174                    WindowState ws = wtoken.findMainWindow();
8175                    if (ws != null) {
8176                        if (ws.mLayer > bestAnimLayer) {
8177                            animLp = ws.mAttrs;
8178                            bestAnimLayer = ws.mLayer;
8179                        }
8180                    }
8181                }
8182            }
8183
8184            if (closingAppHasWallpaper && openingAppHasWallpaper) {
8185                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!");
8186                switch (transit) {
8187                    case AppTransition.TRANSIT_ACTIVITY_OPEN:
8188                    case AppTransition.TRANSIT_TASK_OPEN:
8189                    case AppTransition.TRANSIT_TASK_TO_FRONT:
8190                        transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN;
8191                        break;
8192                    case AppTransition.TRANSIT_ACTIVITY_CLOSE:
8193                    case AppTransition.TRANSIT_TASK_CLOSE:
8194                    case AppTransition.TRANSIT_TASK_TO_BACK:
8195                        transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE;
8196                        break;
8197                }
8198                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit: " + transit);
8199            } else if ((oldWallpaper != null) && !mOpeningApps.contains(oldWallpaper.mAppToken)) {
8200                // We are transitioning from an activity with
8201                // a wallpaper to one without.
8202                transit = AppTransition.TRANSIT_WALLPAPER_CLOSE;
8203                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8204                        "New transit away from wallpaper: " + transit);
8205            } else if (mWallpaperTarget != null && mWallpaperTarget.isVisibleLw()) {
8206                // We are transitioning from an activity without
8207                // a wallpaper to now showing the wallpaper
8208                transit = AppTransition.TRANSIT_WALLPAPER_OPEN;
8209                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8210                        "New transit into wallpaper: " + transit);
8211            }
8212
8213            // If all closing windows are obscured, then there is
8214            // no need to do an animation.  This is the case, for
8215            // example, when this transition is being done behind
8216            // the lock screen.
8217            if (!mPolicy.allowAppAnimationsLw()) {
8218                animLp = null;
8219            }
8220
8221            AppWindowToken topOpeningApp = null;
8222            int topOpeningLayer = 0;
8223
8224            NN = mOpeningApps.size();
8225            for (i=0; i<NN; i++) {
8226                AppWindowToken wtoken = mOpeningApps.get(i);
8227                final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
8228                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken);
8229                appAnimator.clearThumbnail();
8230                wtoken.inPendingTransaction = false;
8231                appAnimator.animation = null;
8232                setTokenVisibilityLocked(wtoken, animLp, true, transit, false);
8233                wtoken.updateReportedVisibilityLocked();
8234                wtoken.waitingToShow = false;
8235
8236                appAnimator.mAllAppWinAnimators.clear();
8237                final int N = wtoken.allAppWindows.size();
8238                for (int j = 0; j < N; j++) {
8239                    appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
8240                }
8241                mAnimator.mAnimating |= appAnimator.showAllWindowsLocked();
8242
8243                if (animLp != null) {
8244                    int layer = -1;
8245                    for (int j=0; j<wtoken.windows.size(); j++) {
8246                        WindowState win = wtoken.windows.get(j);
8247                        if (win.mWinAnimator.mAnimLayer > layer) {
8248                            layer = win.mWinAnimator.mAnimLayer;
8249                        }
8250                    }
8251                    if (topOpeningApp == null || layer > topOpeningLayer) {
8252                        topOpeningApp = wtoken;
8253                        topOpeningLayer = layer;
8254                    }
8255                }
8256            }
8257            NN = mClosingApps.size();
8258            for (i=0; i<NN; i++) {
8259                AppWindowToken wtoken = mClosingApps.get(i);
8260                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8261                        "Now closing app " + wtoken);
8262                wtoken.mAppAnimator.clearThumbnail();
8263                wtoken.inPendingTransaction = false;
8264                wtoken.mAppAnimator.animation = null;
8265                setTokenVisibilityLocked(wtoken, animLp, false,
8266                        transit, false);
8267                wtoken.updateReportedVisibilityLocked();
8268                wtoken.waitingToHide = false;
8269                // Force the allDrawn flag, because we want to start
8270                // this guy's animations regardless of whether it's
8271                // gotten drawn.
8272                wtoken.allDrawn = true;
8273                wtoken.deferClearAllDrawn = false;
8274            }
8275
8276            AppWindowAnimator appAnimator =
8277                    topOpeningApp == null ? null : topOpeningApp.mAppAnimator;
8278            Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail();
8279            if (nextAppTransitionThumbnail != null && appAnimator != null
8280                    && appAnimator.animation != null) {
8281                // This thumbnail animation is very special, we need to have
8282                // an extra surface with the thumbnail included with the animation.
8283                Rect dirty = new Rect(0, 0, nextAppTransitionThumbnail.getWidth(),
8284                        nextAppTransitionThumbnail.getHeight());
8285                try {
8286                    // TODO(multi-display): support other displays
8287                    final DisplayContent displayContent = getDefaultDisplayContentLocked();
8288                    final Display display = displayContent.getDisplay();
8289                    SurfaceControl surfaceControl = new SurfaceControl(mFxSession,
8290                            "thumbnail anim",
8291                            dirty.width(), dirty.height(),
8292                            PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
8293                    surfaceControl.setLayerStack(display.getLayerStack());
8294                    appAnimator.thumbnail = surfaceControl;
8295                    if (SHOW_TRANSACTIONS) Slog.i(TAG, "  THUMBNAIL " + surfaceControl + ": CREATE");
8296                    Surface drawSurface = new Surface();
8297                    drawSurface.copyFrom(surfaceControl);
8298                    Canvas c = drawSurface.lockCanvas(dirty);
8299                    c.drawBitmap(nextAppTransitionThumbnail, 0, 0, null);
8300                    drawSurface.unlockCanvasAndPost(c);
8301                    drawSurface.release();
8302                    appAnimator.thumbnailLayer = topOpeningLayer;
8303                    DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
8304                    Animation anim = mAppTransition.createThumbnailAnimationLocked(
8305                            transit, true, true, displayInfo.appWidth, displayInfo.appHeight);
8306                    appAnimator.thumbnailAnimation = anim;
8307                    anim.restrictDuration(MAX_ANIMATION_DURATION);
8308                    anim.scaleCurrentDuration(mTransitionAnimationScale);
8309                    Point p = new Point();
8310                    mAppTransition.getStartingPoint(p);
8311                    appAnimator.thumbnailX = p.x;
8312                    appAnimator.thumbnailY = p.y;
8313                } catch (SurfaceControl.OutOfResourcesException e) {
8314                    Slog.e(TAG, "Can't allocate thumbnail surface w=" + dirty.width()
8315                            + " h=" + dirty.height(), e);
8316                    appAnimator.clearThumbnail();
8317                } catch (Surface.OutOfResourcesException e) {
8318                    Slog.e(TAG, "Can't allocate Canvas surface w=" + dirty.width()
8319                            + " h=" + dirty.height(), e);
8320                    appAnimator.clearThumbnail();
8321                }
8322            }
8323
8324            mAppTransition.postAnimationCallback();
8325            mAppTransition.clear();
8326
8327            mOpeningApps.clear();
8328            mClosingApps.clear();
8329
8330            // This has changed the visibility of windows, so perform
8331            // a new layout to get them all up-to-date.
8332            changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT
8333                    | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
8334            getDefaultDisplayContentLocked().layoutNeeded = true;
8335
8336            // TODO(multidisplay): IMEs are only supported on the default display.
8337            if (windows == getDefaultWindowListLocked()
8338                    && !moveInputMethodWindowsIfNeededLocked(true)) {
8339                assignLayersLocked(windows);
8340            }
8341            updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, false /*updateInputWindows*/);
8342            mFocusMayChange = false;
8343        }
8344
8345        return changes;
8346    }
8347
8348    /**
8349     * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
8350     * @return bitmap indicating if another pass through layout must be made.
8351     */
8352    private int handleAnimatingStoppedAndTransitionLocked() {
8353        int changes = 0;
8354
8355        mAppTransition.setIdle();
8356        // Restore window app tokens to the ActivityManager views
8357        for (int i = mAnimatingAppTokens.size() - 1; i >= 0; i--) {
8358            mAnimatingAppTokens.get(i).sendingToBottom = false;
8359        }
8360        mAnimatingAppTokens.clear();
8361        mAnimatingAppTokens.addAll(mAppTokens);
8362        rebuildAppWindowListLocked();
8363
8364        changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
8365        if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
8366                "Wallpaper layer changed: assigning layers + relayout");
8367        moveInputMethodWindowsIfNeededLocked(true);
8368        mInnerFields.mWallpaperMayChange = true;
8369        // Since the window list has been rebuilt, focus might
8370        // have to be recomputed since the actual order of windows
8371        // might have changed again.
8372        mFocusMayChange = true;
8373
8374        return changes;
8375    }
8376
8377    private void updateResizingWindows(final WindowState w) {
8378        final WindowStateAnimator winAnimator = w.mWinAnimator;
8379        if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq) {
8380            w.mOverscanInsetsChanged |=
8381                    !w.mLastOverscanInsets.equals(w.mOverscanInsets);
8382            w.mContentInsetsChanged |=
8383                    !w.mLastContentInsets.equals(w.mContentInsets);
8384            w.mVisibleInsetsChanged |=
8385                    !w.mLastVisibleInsets.equals(w.mVisibleInsets);
8386            boolean configChanged = w.isConfigChanged();
8387            if (DEBUG_CONFIGURATION && configChanged) {
8388                Slog.v(TAG, "Win " + w + " config changed: "
8389                        + mCurConfiguration);
8390            }
8391            if (localLOGV) Slog.v(TAG, "Resizing " + w
8392                    + ": configChanged=" + configChanged
8393                    + " last=" + w.mLastFrame + " frame=" + w.mFrame);
8394            w.mLastFrame.set(w.mFrame);
8395            if (w.mContentInsetsChanged
8396                    || w.mVisibleInsetsChanged
8397                    || winAnimator.mSurfaceResized
8398                    || configChanged) {
8399                if (DEBUG_RESIZE || DEBUG_ORIENTATION) {
8400                    Slog.v(TAG, "Resize reasons: "
8401                            + " contentInsetsChanged=" + w.mContentInsetsChanged
8402                            + " " + w.mContentInsets.toShortString()
8403                            + " visibleInsetsChanged=" + w.mVisibleInsetsChanged
8404                            + " " + w.mVisibleInsets.toShortString()
8405                            + " surfaceResized=" + winAnimator.mSurfaceResized
8406                            + " configChanged=" + configChanged);
8407                }
8408
8409                w.mLastOverscanInsets.set(w.mOverscanInsets);
8410                w.mLastContentInsets.set(w.mContentInsets);
8411                w.mLastVisibleInsets.set(w.mVisibleInsets);
8412                makeWindowFreezingScreenIfNeededLocked(w);
8413                // If the orientation is changing, then we need to
8414                // hold off on unfreezing the display until this
8415                // window has been redrawn; to do that, we need
8416                // to go through the process of getting informed
8417                // by the application when it has finished drawing.
8418                if (w.mOrientationChanging) {
8419                    if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION) Slog.v(TAG,
8420                            "Orientation start waiting for draw mDrawState=DRAW_PENDING in "
8421                            + w + ", surface " + winAnimator.mSurfaceControl);
8422                    winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
8423                    if (w.mAppToken != null) {
8424                        w.mAppToken.allDrawn = false;
8425                        w.mAppToken.deferClearAllDrawn = false;
8426                    }
8427                }
8428                if (!mResizingWindows.contains(w)) {
8429                    if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
8430                            "Resizing window " + w + " to " + winAnimator.mSurfaceW
8431                            + "x" + winAnimator.mSurfaceH);
8432                    mResizingWindows.add(w);
8433                }
8434            } else if (w.mOrientationChanging) {
8435                if (w.isDrawnLw()) {
8436                    if (DEBUG_ORIENTATION) Slog.v(TAG,
8437                            "Orientation not waiting for draw in "
8438                            + w + ", surface " + winAnimator.mSurfaceControl);
8439                    w.mOrientationChanging = false;
8440                    w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
8441                            - mDisplayFreezeTime);
8442                }
8443            }
8444        }
8445    }
8446
8447    /**
8448     * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
8449     *
8450     * @param w WindowState this method is applied to.
8451     * @param currentTime The time which animations use for calculating transitions.
8452     * @param innerDw Width of app window.
8453     * @param innerDh Height of app window.
8454     */
8455    private void handleNotObscuredLocked(final WindowState w, final long currentTime,
8456                                         final int innerDw, final int innerDh) {
8457        final WindowManager.LayoutParams attrs = w.mAttrs;
8458        final int attrFlags = attrs.flags;
8459        final boolean canBeSeen = w.isDisplayedLw();
8460
8461        if (w.mHasSurface) {
8462            if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) {
8463                mInnerFields.mHoldScreen = w.mSession;
8464            }
8465            if (!mInnerFields.mSyswin && w.mAttrs.screenBrightness >= 0
8466                    && mInnerFields.mScreenBrightness < 0) {
8467                mInnerFields.mScreenBrightness = w.mAttrs.screenBrightness;
8468            }
8469            if (!mInnerFields.mSyswin && w.mAttrs.buttonBrightness >= 0
8470                    && mInnerFields.mButtonBrightness < 0) {
8471                mInnerFields.mButtonBrightness = w.mAttrs.buttonBrightness;
8472            }
8473            if (!mInnerFields.mSyswin && w.mAttrs.userActivityTimeout >= 0
8474                    && mInnerFields.mUserActivityTimeout < 0) {
8475                mInnerFields.mUserActivityTimeout = w.mAttrs.userActivityTimeout;
8476            }
8477
8478            final int type = attrs.type;
8479            if (canBeSeen
8480                    && (type == TYPE_SYSTEM_DIALOG
8481                     || type == TYPE_RECENTS_OVERLAY
8482                     || type == TYPE_KEYGUARD
8483                     || type == TYPE_SYSTEM_ERROR)) {
8484                mInnerFields.mSyswin = true;
8485            }
8486
8487            if (canBeSeen) {
8488                if (type == TYPE_DREAM || type == TYPE_KEYGUARD) {
8489                    mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_MIRROR;
8490                } else if (mInnerFields.mDisplayHasContent
8491                        == LayoutFields.DISPLAY_CONTENT_UNKNOWN) {
8492                    mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_UNIQUE;
8493                }
8494            }
8495        }
8496
8497        boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn();
8498        if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) {
8499            // This window completely covers everything behind it,
8500            // so we want to leave all of them as undimmed (for
8501            // performance reasons).
8502            mInnerFields.mObscured = true;
8503        }
8504    }
8505
8506    private void handleFlagDimBehind(WindowState w, int innerDw, int innerDh) {
8507        final WindowManager.LayoutParams attrs = w.mAttrs;
8508        if ((attrs.flags & FLAG_DIM_BEHIND) != 0
8509                && w.isDisplayedLw()
8510                && !w.mExiting) {
8511            mInnerFields.mDimming = true;
8512            final WindowStateAnimator winAnimator = w.mWinAnimator;
8513            if (!mAnimator.isDimmingLocked(winAnimator)) {
8514                if (localLOGV) Slog.v(TAG, "Win " + w + " start dimming.");
8515                startDimmingLocked(winAnimator, w.mExiting ? 0 : w.mAttrs.dimAmount);
8516            }
8517        }
8518    }
8519
8520    private void updateAllDrawnLocked() {
8521        // See if any windows have been drawn, so they (and others
8522        // associated with them) can now be shown.
8523        final ArrayList<AppWindowToken> appTokens = mAnimatingAppTokens;
8524        final int NT = appTokens.size();
8525        for (int i=0; i<NT; i++) {
8526            AppWindowToken wtoken = appTokens.get(i);
8527            if (!wtoken.allDrawn) {
8528                int numInteresting = wtoken.numInterestingWindows;
8529                if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
8530                    if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
8531                            "allDrawn: " + wtoken
8532                            + " interesting=" + numInteresting
8533                            + " drawn=" + wtoken.numDrawnWindows);
8534                    wtoken.allDrawn = true;
8535                }
8536            }
8537        }
8538    }
8539
8540    // "Something has changed!  Let's make it correct now."
8541    private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) {
8542        if (DEBUG_WINDOW_TRACE) {
8543            Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by "
8544                    + Debug.getCallers(3));
8545        }
8546
8547        final long currentTime = SystemClock.uptimeMillis();
8548
8549        int i;
8550
8551        if (mFocusMayChange) {
8552            mFocusMayChange = false;
8553            updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
8554                    false /*updateInputWindows*/);
8555        }
8556
8557        // Initialize state of exiting tokens.
8558        for (i=mExitingTokens.size()-1; i>=0; i--) {
8559            mExitingTokens.get(i).hasVisible = false;
8560        }
8561
8562        // Initialize state of exiting applications.
8563        for (i=mExitingAppTokens.size()-1; i>=0; i--) {
8564            mExitingAppTokens.get(i).hasVisible = false;
8565        }
8566
8567        mInnerFields.mHoldScreen = null;
8568        mInnerFields.mScreenBrightness = -1;
8569        mInnerFields.mButtonBrightness = -1;
8570        mInnerFields.mUserActivityTimeout = -1;
8571        mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_UNKNOWN;
8572
8573        mTransactionSequence++;
8574
8575        final DisplayContent defaultDisplay = getDefaultDisplayContentLocked();
8576        final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo();
8577        final int defaultDw = defaultInfo.logicalWidth;
8578        final int defaultDh = defaultInfo.logicalHeight;
8579
8580        if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
8581                ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
8582        SurfaceControl.openTransaction();
8583        try {
8584
8585            if (mWatermark != null) {
8586                mWatermark.positionSurface(defaultDw, defaultDh);
8587            }
8588            if (mStrictModeFlash != null) {
8589                mStrictModeFlash.positionSurface(defaultDw, defaultDh);
8590            }
8591
8592            boolean focusDisplayed = false;
8593            boolean updateAllDrawn = false;
8594
8595            DisplayContentsIterator iterator = new DisplayContentsIterator();
8596            while (iterator.hasNext()) {
8597                final DisplayContent displayContent = iterator.next();
8598                WindowList windows = displayContent.getWindowList();
8599                DisplayInfo displayInfo = displayContent.getDisplayInfo();
8600                final int displayId = displayContent.getDisplayId();
8601                final int dw = displayInfo.logicalWidth;
8602                final int dh = displayInfo.logicalHeight;
8603                final int innerDw = displayInfo.appWidth;
8604                final int innerDh = displayInfo.appHeight;
8605                final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
8606
8607                // Reset for each display unless we are forcing mirroring.
8608                if (mInnerFields.mDisplayHasContent != LayoutFields.DISPLAY_CONTENT_MIRROR) {
8609                    mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_UNKNOWN;
8610                }
8611
8612                int repeats = 0;
8613                do {
8614                    repeats++;
8615                    if (repeats > 6) {
8616                        Slog.w(TAG, "Animation repeat aborted after too many iterations");
8617                        displayContent.layoutNeeded = false;
8618                        break;
8619                    }
8620
8621                    if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner",
8622                        displayContent.pendingLayoutChanges);
8623
8624                    if ((displayContent.pendingLayoutChanges &
8625                            WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0 &&
8626                            (adjustWallpaperWindowsLocked() &
8627                                    ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
8628                        assignLayersLocked(windows);
8629                        displayContent.layoutNeeded = true;
8630                    }
8631
8632                    if (isDefaultDisplay && (displayContent.pendingLayoutChanges
8633                            & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
8634                        if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
8635                        if (updateOrientationFromAppTokensLocked(true)) {
8636                            displayContent.layoutNeeded = true;
8637                            mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
8638                        }
8639                    }
8640
8641                    if ((displayContent.pendingLayoutChanges
8642                            & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
8643                        displayContent.layoutNeeded = true;
8644                    }
8645
8646                    // FIRST LOOP: Perform a layout, if needed.
8647                    if (repeats < 4) {
8648                        performLayoutLockedInner(displayContent, repeats == 1,
8649                                false /*updateInputWindows*/);
8650                    } else {
8651                        Slog.w(TAG, "Layout repeat skipped after too many iterations");
8652                    }
8653
8654                    // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think
8655                    // it is animating.
8656                    displayContent.pendingLayoutChanges = 0;
8657
8658                    if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number "
8659                            + mLayoutRepeatCount, displayContent.pendingLayoutChanges);
8660
8661                    if (isDefaultDisplay) {
8662                        mPolicy.beginPostLayoutPolicyLw(dw, dh);
8663                        for (i = windows.size() - 1; i >= 0; i--) {
8664                            WindowState w = windows.get(i);
8665                            if (w.mHasSurface) {
8666                                mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs);
8667                            }
8668                        }
8669                        displayContent.pendingLayoutChanges |= mPolicy.finishPostLayoutPolicyLw();
8670                        if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats(
8671                            "after finishPostLayoutPolicyLw", displayContent.pendingLayoutChanges);
8672                    }
8673                } while (displayContent.pendingLayoutChanges != 0);
8674
8675                mInnerFields.mObscured = false;
8676                mInnerFields.mDimming = false;
8677                mInnerFields.mSyswin = false;
8678
8679                // Only used if default window
8680                final boolean someoneLosingFocus = !mLosingFocus.isEmpty();
8681
8682                final int N = windows.size();
8683                for (i=N-1; i>=0; i--) {
8684                    WindowState w = windows.get(i);
8685
8686                    final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured;
8687
8688                    // Update effect.
8689                    w.mObscured = mInnerFields.mObscured;
8690                    if (!mInnerFields.mObscured) {
8691                        handleNotObscuredLocked(w, currentTime, innerDw, innerDh);
8692                    }
8693
8694                    if (!mInnerFields.mDimming) {
8695                        handleFlagDimBehind(w, innerDw, innerDh);
8696                    }
8697
8698                    if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w)
8699                            && w.isVisibleLw()) {
8700                        // This is the wallpaper target and its obscured state
8701                        // changed... make sure the current wallaper's visibility
8702                        // has been updated accordingly.
8703                        updateWallpaperVisibilityLocked();
8704                    }
8705
8706                    final WindowStateAnimator winAnimator = w.mWinAnimator;
8707
8708                    // If the window has moved due to its containing
8709                    // content frame changing, then we'd like to animate
8710                    // it.
8711                    if (w.mHasSurface && w.shouldAnimateMove()) {
8712                        // Frame has moved, containing content frame
8713                        // has also moved, and we're not currently animating...
8714                        // let's do something.
8715                        Animation a = AnimationUtils.loadAnimation(mContext,
8716                                com.android.internal.R.anim.window_move_from_decor);
8717                        winAnimator.setAnimation(a);
8718                        winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left;
8719                        winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top;
8720                        try {
8721                            w.mClient.moved(w.mFrame.left, w.mFrame.top);
8722                        } catch (RemoteException e) {
8723                        }
8724                    }
8725
8726                    //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
8727                    w.mContentChanged = false;
8728
8729                    // Moved from updateWindowsAndWallpaperLocked().
8730                    if (w.mHasSurface) {
8731                        // Take care of the window being ready to display.
8732                        final boolean committed =
8733                                winAnimator.commitFinishDrawingLocked(currentTime);
8734                        if (isDefaultDisplay && committed) {
8735                            if (w.mAttrs.type == TYPE_DREAM) {
8736                                // HACK: When a dream is shown, it may at that
8737                                // point hide the lock screen.  So we need to
8738                                // redo the layout to let the phone window manager
8739                                // make this happen.
8740                                displayContent.pendingLayoutChanges |=
8741                                        WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
8742                                if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
8743                                    debugLayoutRepeats(
8744                                        "dream and commitFinishDrawingLocked true",
8745                                        displayContent.pendingLayoutChanges);
8746                                }
8747                            }
8748                            if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
8749                                if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
8750                                        "First draw done in potential wallpaper target " + w);
8751                                mInnerFields.mWallpaperMayChange = true;
8752                                displayContent.pendingLayoutChanges |=
8753                                        WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
8754                                if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
8755                                    debugLayoutRepeats(
8756                                        "wallpaper and commitFinishDrawingLocked true",
8757                                        displayContent.pendingLayoutChanges);
8758                                }
8759                            }
8760                        }
8761
8762                        winAnimator.setSurfaceBoundariesLocked(recoveringMemory);
8763
8764                        final AppWindowToken atoken = w.mAppToken;
8765                        if (DEBUG_STARTING_WINDOW && atoken != null
8766                                && w == atoken.startingWindow) {
8767                            Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen="
8768                                + w.isOnScreen() + " allDrawn=" + atoken.allDrawn
8769                                + " freezingScreen=" + atoken.mAppAnimator.freezingScreen);
8770                        }
8771                        if (atoken != null
8772                                && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) {
8773                            if (atoken.lastTransactionSequence != mTransactionSequence) {
8774                                atoken.lastTransactionSequence = mTransactionSequence;
8775                                atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
8776                                atoken.startingDisplayed = false;
8777                            }
8778                            if ((w.isOnScreen() || winAnimator.mAttrType == TYPE_BASE_APPLICATION)
8779                                    && !w.mExiting && !w.mDestroying) {
8780                                if (WindowManagerService.DEBUG_VISIBILITY ||
8781                                        WindowManagerService.DEBUG_ORIENTATION) {
8782                                    Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
8783                                            + ", isAnimating=" + winAnimator.isAnimating());
8784                                    if (!w.isDrawnLw()) {
8785                                        Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceControl
8786                                                + " pv=" + w.mPolicyVisibility
8787                                                + " mDrawState=" + winAnimator.mDrawState
8788                                                + " ah=" + w.mAttachedHidden
8789                                                + " th=" + atoken.hiddenRequested
8790                                                + " a=" + winAnimator.mAnimating);
8791                                    }
8792                                }
8793                                if (w != atoken.startingWindow) {
8794                                    if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) {
8795                                        atoken.numInterestingWindows++;
8796                                        if (w.isDrawnLw()) {
8797                                            atoken.numDrawnWindows++;
8798                                            if (WindowManagerService.DEBUG_VISIBILITY ||
8799                                                    WindowManagerService.DEBUG_ORIENTATION) Slog.v(TAG,
8800                                                    "tokenMayBeDrawn: " + atoken
8801                                                    + " freezingScreen=" + atoken.mAppAnimator.freezingScreen
8802                                                    + " mAppFreezing=" + w.mAppFreezing);
8803                                            updateAllDrawn = true;
8804                                        }
8805                                    }
8806                                } else if (w.isDrawnLw()) {
8807                                    atoken.startingDisplayed = true;
8808                                }
8809                            }
8810                        }
8811                    }
8812
8813                    if (isDefaultDisplay && someoneLosingFocus && (w == mCurrentFocus)
8814                            && w.isDisplayedLw()) {
8815                        focusDisplayed = true;
8816                    }
8817
8818                    updateResizingWindows(w);
8819                }
8820
8821                final boolean hasUniqueContent;
8822                switch (mInnerFields.mDisplayHasContent) {
8823                    case LayoutFields.DISPLAY_CONTENT_MIRROR:
8824                        hasUniqueContent = isDefaultDisplay;
8825                        break;
8826                    case LayoutFields.DISPLAY_CONTENT_UNIQUE:
8827                        hasUniqueContent = true;
8828                        break;
8829                    case LayoutFields.DISPLAY_CONTENT_UNKNOWN:
8830                    default:
8831                        hasUniqueContent = false;
8832                        break;
8833                }
8834                mDisplayManagerService.setDisplayHasContent(displayId, hasUniqueContent,
8835                        true /* inTraversal, must call performTraversalInTrans... below */);
8836
8837                if (!mInnerFields.mDimming && mAnimator.isDimmingLocked(displayId)) {
8838                    stopDimmingLocked(displayId);
8839                }
8840            }
8841
8842            if (updateAllDrawn) {
8843                updateAllDrawnLocked();
8844            }
8845
8846            if (focusDisplayed) {
8847                mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS);
8848            }
8849
8850            // Give the display manager a chance to adjust properties
8851            // like display rotation if it needs to.
8852            mDisplayManagerService.performTraversalInTransactionFromWindowManager();
8853
8854        } catch (RuntimeException e) {
8855            Log.wtf(TAG, "Unhandled exception in Window Manager", e);
8856        } finally {
8857            SurfaceControl.closeTransaction();
8858            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
8859                    "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
8860        }
8861
8862        final WindowList defaultWindows = defaultDisplay.getWindowList();
8863
8864        // If we are ready to perform an app transition, check through
8865        // all of the app tokens to be shown and see if they are ready
8866        // to go.
8867        if (mAppTransition.isReady()) {
8868            defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows);
8869            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked",
8870                    defaultDisplay.pendingLayoutChanges);
8871        }
8872
8873        if (!mAnimator.mAnimating && mAppTransition.isRunning()) {
8874            // We have finished the animation of an app transition.  To do
8875            // this, we have delayed a lot of operations like showing and
8876            // hiding apps, moving apps in Z-order, etc.  The app token list
8877            // reflects the correct Z-order, but the window list may now
8878            // be out of sync with it.  So here we will just rebuild the
8879            // entire app window list.  Fun!
8880            defaultDisplay.pendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked();
8881            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock",
8882                defaultDisplay.pendingLayoutChanges);
8883        }
8884
8885        if (mInnerFields.mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0
8886                && !mAppTransition.isReady()) {
8887            // At this point, there was a window with a wallpaper that
8888            // was force hiding other windows behind it, but now it
8889            // is going away.  This may be simple -- just animate
8890            // away the wallpaper and its window -- or it may be
8891            // hard -- the wallpaper now needs to be shown behind
8892            // something that was hidden.
8893            defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
8894            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked",
8895                defaultDisplay.pendingLayoutChanges);
8896        }
8897        mInnerFields.mWallpaperForceHidingChanged = false;
8898
8899        if (mInnerFields.mWallpaperMayChange) {
8900            if (WindowManagerService.DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
8901                    "Wallpaper may change!  Adjusting");
8902            defaultDisplay.pendingLayoutChanges |=
8903                    WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
8904            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("WallpaperMayChange",
8905                    defaultDisplay.pendingLayoutChanges);
8906        }
8907
8908        if (mFocusMayChange) {
8909            mFocusMayChange = false;
8910            if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
8911                    false /*updateInputWindows*/)) {
8912                defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
8913            }
8914        }
8915
8916        if (needsLayout()) {
8917            defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
8918            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded",
8919                    defaultDisplay.pendingLayoutChanges);
8920        }
8921
8922        for (i = mResizingWindows.size() - 1; i >= 0; i--) {
8923            WindowState win = mResizingWindows.get(i);
8924            if (win.mAppFreezing) {
8925                // Don't remove this window until rotation has completed.
8926                continue;
8927            }
8928            final WindowStateAnimator winAnimator = win.mWinAnimator;
8929            try {
8930                if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
8931                        "Reporting new frame to " + win + ": " + win.mCompatFrame);
8932                int diff = 0;
8933                boolean configChanged = win.isConfigChanged();
8934                if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION)
8935                        && configChanged) {
8936                    Slog.i(TAG, "Sending new config to window " + win + ": "
8937                            + winAnimator.mSurfaceW + "x" + winAnimator.mSurfaceH
8938                            + " / " + mCurConfiguration + " / 0x"
8939                            + Integer.toHexString(diff));
8940                }
8941                win.setConfiguration(mCurConfiguration);
8942                if (DEBUG_ORIENTATION &&
8943                        winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING) Slog.i(
8944                        TAG, "Resizing " + win + " WITH DRAW PENDING");
8945                final IWindow client = win.mClient;
8946                final Rect frame = win.mFrame;
8947                final Rect overscanInsets = win.mLastOverscanInsets;
8948                final Rect contentInsets = win.mLastContentInsets;
8949                final Rect visibleInsets = win.mLastVisibleInsets;
8950                final boolean reportDraw
8951                        = winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING;
8952                final Configuration newConfig = configChanged ? win.mConfiguration : null;
8953                if (win.mClient instanceof IWindow.Stub) {
8954                    // To prevent deadlock simulate one-way call if win.mClient is a local object.
8955                    mH.post(new Runnable() {
8956                        @Override
8957                        public void run() {
8958                            try {
8959                                client.resized(frame, overscanInsets, contentInsets,
8960                                        visibleInsets, reportDraw, newConfig);
8961                            } catch (RemoteException e) {
8962                                // Not a remote call, RemoteException won't be raised.
8963                            }
8964                        }
8965                    });
8966                } else {
8967                   client.resized(frame, overscanInsets, contentInsets, visibleInsets, reportDraw,
8968                           newConfig);
8969                }
8970                win.mOverscanInsetsChanged = false;
8971                win.mContentInsetsChanged = false;
8972                win.mVisibleInsetsChanged = false;
8973                winAnimator.mSurfaceResized = false;
8974            } catch (RemoteException e) {
8975                win.mOrientationChanging = false;
8976                win.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
8977                        - mDisplayFreezeTime);
8978            }
8979            mResizingWindows.remove(i);
8980        }
8981
8982        if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG,
8983                "With display frozen, orientationChangeComplete="
8984                + mInnerFields.mOrientationChangeComplete);
8985        if (mInnerFields.mOrientationChangeComplete) {
8986            if (mWindowsFreezingScreen) {
8987                mWindowsFreezingScreen = false;
8988                mLastFinishedFreezeSource = mInnerFields.mLastWindowFreezeSource;
8989                mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
8990            }
8991            stopFreezingDisplayLocked();
8992        }
8993
8994        // Destroy the surface of any windows that are no longer visible.
8995        boolean wallpaperDestroyed = false;
8996        i = mDestroySurface.size();
8997        if (i > 0) {
8998            do {
8999                i--;
9000                WindowState win = mDestroySurface.get(i);
9001                win.mDestroying = false;
9002                if (mInputMethodWindow == win) {
9003                    mInputMethodWindow = null;
9004                }
9005                if (win == mWallpaperTarget) {
9006                    wallpaperDestroyed = true;
9007                }
9008                win.mWinAnimator.destroySurfaceLocked();
9009            } while (i > 0);
9010            mDestroySurface.clear();
9011        }
9012
9013        // Time to remove any exiting tokens?
9014        for (i=mExitingTokens.size()-1; i>=0; i--) {
9015            WindowToken token = mExitingTokens.get(i);
9016            if (!token.hasVisible) {
9017                mExitingTokens.remove(i);
9018                if (token.windowType == TYPE_WALLPAPER) {
9019                    mWallpaperTokens.remove(token);
9020                }
9021            }
9022        }
9023
9024        // Time to remove any exiting applications?
9025        for (i=mExitingAppTokens.size()-1; i>=0; i--) {
9026            AppWindowToken token = mExitingAppTokens.get(i);
9027            if (!token.hasVisible && !mClosingApps.contains(token)) {
9028                // Make sure there is no animation running on this token,
9029                // so any windows associated with it will be removed as
9030                // soon as their animations are complete
9031                token.mAppAnimator.clearAnimation();
9032                token.mAppAnimator.animating = false;
9033                if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
9034                        "performLayout: App token exiting now removed" + token);
9035                mAppTokens.remove(token);
9036                mAnimatingAppTokens.remove(token);
9037                mExitingAppTokens.remove(i);
9038            }
9039        }
9040
9041        if (!mAnimator.mAnimating && mRelayoutWhileAnimating.size() > 0) {
9042            for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) {
9043                try {
9044                    mRelayoutWhileAnimating.get(j).mClient.doneAnimating();
9045                } catch (RemoteException e) {
9046                }
9047            }
9048            mRelayoutWhileAnimating.clear();
9049        }
9050
9051        if (wallpaperDestroyed) {
9052            defaultDisplay.pendingLayoutChanges |=
9053                    WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
9054            defaultDisplay.layoutNeeded = true;
9055        }
9056
9057        DisplayContentsIterator iterator = new DisplayContentsIterator();
9058        while (iterator.hasNext()) {
9059            DisplayContent displayContent = iterator.next();
9060            if (displayContent.pendingLayoutChanges != 0) {
9061                displayContent.layoutNeeded = true;
9062            }
9063        }
9064
9065        // Finally update all input windows now that the window changes have stabilized.
9066        mInputMonitor.updateInputWindowsLw(true /*force*/);
9067
9068        setHoldScreenLocked(mInnerFields.mHoldScreen);
9069        if (!mDisplayFrozen) {
9070            if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) {
9071                mPowerManager.setScreenBrightnessOverrideFromWindowManager(-1);
9072            } else {
9073                mPowerManager.setScreenBrightnessOverrideFromWindowManager(
9074                        toBrightnessOverride(mInnerFields.mScreenBrightness));
9075            }
9076            if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) {
9077                mPowerManager.setButtonBrightnessOverrideFromWindowManager(-1);
9078            } else {
9079                mPowerManager.setButtonBrightnessOverrideFromWindowManager(
9080                        toBrightnessOverride(mInnerFields.mButtonBrightness));
9081            }
9082            mPowerManager.setUserActivityTimeoutOverrideFromWindowManager(
9083                    mInnerFields.mUserActivityTimeout);
9084        }
9085
9086        if (mTurnOnScreen) {
9087            if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!");
9088            mPowerManager.wakeUp(SystemClock.uptimeMillis());
9089            mTurnOnScreen = false;
9090        }
9091
9092        if (mInnerFields.mUpdateRotation) {
9093            if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
9094            if (updateRotationUncheckedLocked(false)) {
9095                mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
9096            } else {
9097                mInnerFields.mUpdateRotation = false;
9098            }
9099        }
9100
9101        if (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded
9102                && !mInnerFields.mUpdateRotation) {
9103            checkDrawnWindowsLocked();
9104        }
9105
9106        final int N = mPendingRemove.size();
9107        if (N > 0) {
9108            if (mPendingRemoveTmp.length < N) {
9109                mPendingRemoveTmp = new WindowState[N+10];
9110            }
9111            mPendingRemove.toArray(mPendingRemoveTmp);
9112            mPendingRemove.clear();
9113            DisplayContentList displayList = new DisplayContentList();
9114            for (i = 0; i < N; i++) {
9115                WindowState w = mPendingRemoveTmp[i];
9116                removeWindowInnerLocked(w.mSession, w);
9117                if (!displayList.contains(w.mDisplayContent)) {
9118                    displayList.add(w.mDisplayContent);
9119                }
9120            }
9121
9122            for (DisplayContent displayContent : displayList) {
9123                assignLayersLocked(displayContent.getWindowList());
9124                displayContent.layoutNeeded = true;
9125            }
9126        }
9127
9128        // Check to see if we are now in a state where the screen should
9129        // be enabled, because the window obscured flags have changed.
9130        enableScreenIfNeededLocked();
9131
9132        scheduleAnimationLocked();
9133
9134        if (DEBUG_WINDOW_TRACE) {
9135            Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: animating="
9136                    + mAnimator.mAnimating);
9137        }
9138    }
9139
9140    private int toBrightnessOverride(float value) {
9141        return (int)(value * PowerManager.BRIGHTNESS_ON);
9142    }
9143
9144    void checkDrawnWindowsLocked() {
9145        if (mWaitingForDrawn.size() > 0) {
9146            for (int j=mWaitingForDrawn.size()-1; j>=0; j--) {
9147                Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(j);
9148                WindowState win = pair.first;
9149                //Slog.i(TAG, "Waiting for drawn " + win + ": removed="
9150                //        + win.mRemoved + " visible=" + win.isVisibleLw()
9151                //        + " shown=" + win.mSurfaceShown);
9152                if (win.mRemoved || !win.isVisibleLw()) {
9153                    // Window has been removed or made invisible; no draw
9154                    // will now happen, so stop waiting.
9155                    Slog.w(TAG, "Aborted waiting for drawn: " + pair.first);
9156                    try {
9157                        pair.second.sendResult(null);
9158                    } catch (RemoteException e) {
9159                    }
9160                    mWaitingForDrawn.remove(pair);
9161                    mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
9162                } else if (win.mWinAnimator.mSurfaceShown) {
9163                    // Window is now drawn (and shown).
9164                    try {
9165                        pair.second.sendResult(null);
9166                    } catch (RemoteException e) {
9167                    }
9168                    mWaitingForDrawn.remove(pair);
9169                    mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
9170                }
9171            }
9172        }
9173    }
9174
9175    @Override
9176    public boolean waitForWindowDrawn(IBinder token, IRemoteCallback callback) {
9177        if (token != null && callback != null) {
9178            synchronized (mWindowMap) {
9179                WindowState win = windowForClientLocked(null, token, true);
9180                if (win != null) {
9181                    Pair<WindowState, IRemoteCallback> pair =
9182                            new Pair<WindowState, IRemoteCallback>(win, callback);
9183                    Message m = mH.obtainMessage(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
9184                    mH.sendMessageDelayed(m, 2000);
9185                    mWaitingForDrawn.add(pair);
9186                    checkDrawnWindowsLocked();
9187                    return true;
9188                }
9189            }
9190        }
9191        return false;
9192    }
9193
9194    void setHoldScreenLocked(final Session newHoldScreen) {
9195        final boolean hold = newHoldScreen != null;
9196
9197        if (hold && mHoldingScreenOn != newHoldScreen) {
9198            mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid));
9199        }
9200        mHoldingScreenOn = newHoldScreen;
9201
9202        final boolean state = mHoldingScreenWakeLock.isHeld();
9203        if (hold != state) {
9204            if (hold) {
9205                mHoldingScreenWakeLock.acquire();
9206                mPolicy.keepScreenOnStartedLw();
9207            } else {
9208                mPolicy.keepScreenOnStoppedLw();
9209                mHoldingScreenWakeLock.release();
9210            }
9211        }
9212    }
9213
9214    @Override
9215    public void requestTraversal() {
9216        synchronized (mWindowMap) {
9217            requestTraversalLocked();
9218        }
9219    }
9220
9221    void requestTraversalLocked() {
9222        if (!mTraversalScheduled) {
9223            mTraversalScheduled = true;
9224            mH.sendEmptyMessage(H.DO_TRAVERSAL);
9225        }
9226    }
9227
9228    /** Note that Locked in this case is on mLayoutToAnim */
9229    void scheduleAnimationLocked() {
9230        if (!mAnimationScheduled) {
9231            mAnimationScheduled = true;
9232            mChoreographer.postCallback(
9233                    Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null);
9234        }
9235    }
9236
9237    void startDimmingLocked(final WindowStateAnimator winAnimator, final float target) {
9238        mAnimator.setDimWinAnimatorLocked(winAnimator.mWin.getDisplayId(), winAnimator);
9239    }
9240
9241    void stopDimmingLocked(int displayId) {
9242        mAnimator.setDimWinAnimatorLocked(displayId, null);
9243    }
9244
9245    private boolean needsLayout() {
9246        DisplayContentsIterator iterator = new DisplayContentsIterator();
9247        while (iterator.hasNext()) {
9248            if (iterator.next().layoutNeeded) {
9249                return true;
9250            }
9251        }
9252        return false;
9253    }
9254
9255    boolean copyAnimToLayoutParamsLocked() {
9256        boolean doRequest = false;
9257
9258        final int bulkUpdateParams = mAnimator.mBulkUpdateParams;
9259        if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) {
9260            mInnerFields.mUpdateRotation = true;
9261            doRequest = true;
9262        }
9263        if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) {
9264            mInnerFields.mWallpaperMayChange = true;
9265            doRequest = true;
9266        }
9267        if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) {
9268            mInnerFields.mWallpaperForceHidingChanged = true;
9269            doRequest = true;
9270        }
9271        if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) == 0) {
9272            mInnerFields.mOrientationChangeComplete = false;
9273        } else {
9274            mInnerFields.mOrientationChangeComplete = true;
9275            mInnerFields.mLastWindowFreezeSource = mAnimator.mLastWindowFreezeSource;
9276            if (mWindowsFreezingScreen) {
9277                doRequest = true;
9278            }
9279        }
9280        if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) {
9281            mTurnOnScreen = true;
9282        }
9283        if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_ACTION_PENDING) != 0) {
9284            mInnerFields.mWallpaperActionPending = true;
9285        }
9286
9287        return doRequest;
9288    }
9289
9290    boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation,
9291                                           boolean secure) {
9292        final SurfaceControl surface = winAnimator.mSurfaceControl;
9293        boolean leakedSurface = false;
9294        boolean killedApps = false;
9295
9296        EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(),
9297                winAnimator.mSession.mPid, operation);
9298
9299        if (mForceRemoves == null) {
9300            mForceRemoves = new ArrayList<WindowState>();
9301        }
9302
9303        long callingIdentity = Binder.clearCallingIdentity();
9304        try {
9305            // There was some problem...   first, do a sanity check of the
9306            // window list to make sure we haven't left any dangling surfaces
9307            // around.
9308
9309            AllWindowsIterator iterator = new AllWindowsIterator();
9310            Slog.i(TAG, "Out of memory for surface!  Looking for leaks...");
9311            while (iterator.hasNext()) {
9312                WindowState ws = iterator.next();
9313                WindowStateAnimator wsa = ws.mWinAnimator;
9314                if (wsa.mSurfaceControl != null) {
9315                    if (!mSessions.contains(wsa.mSession)) {
9316                        Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): "
9317                                + ws + " surface=" + wsa.mSurfaceControl
9318                                + " token=" + ws.mToken
9319                                + " pid=" + ws.mSession.mPid
9320                                + " uid=" + ws.mSession.mUid);
9321                        if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null);
9322                        wsa.mSurfaceControl.destroy();
9323                        wsa.mSurfaceShown = false;
9324                        wsa.mSurfaceControl = null;
9325                        ws.mHasSurface = false;
9326                        mForceRemoves.add(ws);
9327                        leakedSurface = true;
9328                    } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) {
9329                        Slog.w(TAG, "LEAKED SURFACE (app token hidden): "
9330                                + ws + " surface=" + wsa.mSurfaceControl
9331                                + " token=" + ws.mAppToken);
9332                        if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null);
9333                        wsa.mSurfaceControl.destroy();
9334                        wsa.mSurfaceShown = false;
9335                        wsa.mSurfaceControl = null;
9336                        ws.mHasSurface = false;
9337                        leakedSurface = true;
9338                    }
9339                }
9340            }
9341
9342            if (!leakedSurface) {
9343                Slog.w(TAG, "No leaked surfaces; killing applicatons!");
9344                SparseIntArray pidCandidates = new SparseIntArray();
9345                iterator = new AllWindowsIterator();
9346                while (iterator.hasNext()) {
9347                    WindowState ws = iterator.next();
9348                    if (mForceRemoves.contains(ws)) {
9349                        continue;
9350                    }
9351                    WindowStateAnimator wsa = ws.mWinAnimator;
9352                    if (wsa.mSurfaceControl != null) {
9353                        pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid);
9354                    }
9355                }
9356                if (pidCandidates.size() > 0) {
9357                    int[] pids = new int[pidCandidates.size()];
9358                    for (int i=0; i<pids.length; i++) {
9359                        pids[i] = pidCandidates.keyAt(i);
9360                    }
9361                    try {
9362                        if (mActivityManager.killPids(pids, "Free memory", secure)) {
9363                            killedApps = true;
9364                        }
9365                    } catch (RemoteException e) {
9366                    }
9367                }
9368            }
9369
9370            if (leakedSurface || killedApps) {
9371                // We managed to reclaim some memory, so get rid of the trouble
9372                // surface and ask the app to request another one.
9373                Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry.");
9374                if (surface != null) {
9375                    if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin,
9376                            "RECOVER DESTROY", null);
9377                    surface.destroy();
9378                    winAnimator.mSurfaceShown = false;
9379                    winAnimator.mSurfaceControl = null;
9380                    winAnimator.mWin.mHasSurface = false;
9381                }
9382
9383                try {
9384                    winAnimator.mWin.mClient.dispatchGetNewSurface();
9385                } catch (RemoteException e) {
9386                }
9387            }
9388        } finally {
9389            Binder.restoreCallingIdentity(callingIdentity);
9390        }
9391
9392        return leakedSurface || killedApps;
9393    }
9394
9395    private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
9396        WindowState newFocus = computeFocusedWindowLocked();
9397        if (mCurrentFocus != newFocus) {
9398            Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus");
9399            // This check makes sure that we don't already have the focus
9400            // change message pending.
9401            mH.removeMessages(H.REPORT_FOCUS_CHANGE);
9402            mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
9403            if (localLOGV) Slog.v(
9404                TAG, "Changing focus from " + mCurrentFocus + " to " + newFocus);
9405            final WindowState oldFocus = mCurrentFocus;
9406            mCurrentFocus = newFocus;
9407            mAnimator.setCurrentFocus(newFocus);
9408            mLosingFocus.remove(newFocus);
9409            int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
9410
9411            // TODO(multidisplay): Focused windows on default display only.
9412            final DisplayContent displayContent = getDefaultDisplayContentLocked();
9413
9414            final WindowState imWindow = mInputMethodWindow;
9415            if (newFocus != imWindow && oldFocus != imWindow) {
9416                if (moveInputMethodWindowsIfNeededLocked(
9417                        mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS &&
9418                        mode != UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
9419                    displayContent.layoutNeeded = true;
9420                }
9421                if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
9422                    performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows);
9423                    focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9424                } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
9425                    // Client will do the layout, but we need to assign layers
9426                    // for handleNewWindowLocked() below.
9427                    assignLayersLocked(displayContent.getWindowList());
9428                }
9429            }
9430
9431            if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
9432                // The change in focus caused us to need to do a layout.  Okay.
9433                displayContent.layoutNeeded = true;
9434                if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
9435                    performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows);
9436                }
9437            }
9438
9439            if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
9440                // If we defer assigning layers, then the caller is responsible for
9441                // doing this part.
9442                finishUpdateFocusedWindowAfterAssignLayersLocked(updateInputWindows);
9443            }
9444
9445            Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
9446            return true;
9447        }
9448        return false;
9449    }
9450
9451    private void finishUpdateFocusedWindowAfterAssignLayersLocked(boolean updateInputWindows) {
9452        mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows);
9453    }
9454
9455    private WindowState computeFocusedWindowLocked() {
9456        if (mAnimator.mUniverseBackground != null
9457                && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) {
9458            return mAnimator.mUniverseBackground.mWin;
9459        }
9460
9461        final int displayCount = mDisplayContents.size();
9462        for (int i = 0; i < displayCount; i++) {
9463            final DisplayContent displayContent = mDisplayContents.valueAt(i);
9464            WindowState win = findFocusedWindowLocked(displayContent);
9465            if (win != null) {
9466                return win;
9467            }
9468        }
9469        return null;
9470    }
9471
9472    private WindowState findFocusedWindowLocked(DisplayContent displayContent) {
9473        int nextAppIndex = mAppTokens.size()-1;
9474        WindowToken nextApp = nextAppIndex >= 0 ? mAppTokens.get(nextAppIndex) : null;
9475
9476        final WindowList windows = displayContent.getWindowList();
9477        for (int i = windows.size() - 1; i >= 0; i--) {
9478            final WindowState win = windows.get(i);
9479
9480            if (localLOGV || DEBUG_FOCUS) Slog.v(
9481                TAG, "Looking for focus: " + i
9482                + " = " + win
9483                + ", flags=" + win.mAttrs.flags
9484                + ", canReceive=" + win.canReceiveKeys());
9485
9486            AppWindowToken thisApp = win.mAppToken;
9487
9488            // If this window's application has been removed, just skip it.
9489            if (thisApp != null && (thisApp.removed || thisApp.sendingToBottom)) {
9490                if (DEBUG_FOCUS) Slog.v(TAG, "Skipping app because " + (thisApp.removed
9491                        ? "removed" : "sendingToBottom"));
9492                continue;
9493            }
9494
9495            // If there is a focused app, don't allow focus to go to any
9496            // windows below it.  If this is an application window, step
9497            // through the app tokens until we find its app.
9498            if (thisApp != null && nextApp != null && thisApp != nextApp
9499                    && win.mAttrs.type != TYPE_APPLICATION_STARTING) {
9500                int origAppIndex = nextAppIndex;
9501                while (nextAppIndex > 0) {
9502                    if (nextApp == mFocusedApp) {
9503                        // Whoops, we are below the focused app...  no focus
9504                        // for you!
9505                        if (localLOGV || DEBUG_FOCUS) Slog.v(
9506                            TAG, "Reached focused app: " + mFocusedApp);
9507                        return null;
9508                    }
9509                    nextAppIndex--;
9510                    nextApp = mAppTokens.get(nextAppIndex);
9511                    if (nextApp == thisApp) {
9512                        break;
9513                    }
9514                }
9515                if (thisApp != nextApp) {
9516                    // Uh oh, the app token doesn't exist!  This shouldn't
9517                    // happen, but if it does we can get totally hosed...
9518                    // so restart at the original app.
9519                    nextAppIndex = origAppIndex;
9520                    nextApp = mAppTokens.get(nextAppIndex);
9521                }
9522            }
9523
9524            // Dispatch to this window if it is wants key events.
9525            if (win.canReceiveKeys()) {
9526                if (DEBUG_FOCUS) Slog.v(
9527                        TAG, "Found focus @ " + i + " = " + win);
9528                return win;
9529            }
9530        }
9531        return null;
9532    }
9533
9534    private void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) {
9535        if (mDisplayFrozen) {
9536            return;
9537        }
9538
9539        if (!mDisplayReady || !mPolicy.isScreenOnFully()) {
9540            // No need to freeze the screen before the system is ready or if
9541            // the screen is off.
9542            return;
9543        }
9544
9545        mScreenFrozenLock.acquire();
9546
9547        mDisplayFrozen = true;
9548        mDisplayFreezeTime = SystemClock.elapsedRealtime();
9549        mLastFinishedFreezeSource = null;
9550
9551        mInputMonitor.freezeInputDispatchingLw();
9552
9553        // Clear the last input window -- that is just used for
9554        // clean transitions between IMEs, and if we are freezing
9555        // the screen then the whole world is changing behind the scenes.
9556        mPolicy.setLastInputMethodWindowLw(null, null);
9557
9558        if (mAppTransition.isTransitionSet()) {
9559            mAppTransition.freeze();
9560        }
9561
9562        if (PROFILE_ORIENTATION) {
9563            File file = new File("/data/system/frozen");
9564            Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
9565        }
9566
9567        if (CUSTOM_SCREEN_ROTATION) {
9568            mExitAnimId = exitAnim;
9569            mEnterAnimId = enterAnim;
9570            final DisplayContent displayContent = getDefaultDisplayContentLocked();
9571            final int displayId = displayContent.getDisplayId();
9572            ScreenRotationAnimation screenRotationAnimation =
9573                    mAnimator.getScreenRotationAnimationLocked(displayId);
9574            if (screenRotationAnimation != null) {
9575                screenRotationAnimation.kill();
9576            }
9577
9578            // TODO(multidisplay): rotation on main screen only.
9579            final Display display = displayContent.getDisplay();
9580            final DisplayInfo displayInfo = displayContent.getDisplayInfo();
9581            screenRotationAnimation = new ScreenRotationAnimation(mContext,
9582                    display, mFxSession, inTransaction, displayInfo.logicalWidth,
9583                    displayInfo.logicalHeight, display.getRotation());
9584            mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
9585        }
9586    }
9587
9588    private void stopFreezingDisplayLocked() {
9589        if (!mDisplayFrozen) {
9590            return;
9591        }
9592
9593        if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen
9594                || mClientFreezingScreen) {
9595            if (DEBUG_ORIENTATION) Slog.d(TAG,
9596                "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig
9597                + ", mAppsFreezingScreen=" + mAppsFreezingScreen
9598                + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen
9599                + ", mClientFreezingScreen=" + mClientFreezingScreen);
9600            return;
9601        }
9602
9603        mDisplayFrozen = false;
9604        mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime);
9605        StringBuilder sb = new StringBuilder(128);
9606        sb.append("Screen frozen for ");
9607        TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb);
9608        if (mLastFinishedFreezeSource != null) {
9609            sb.append(" due to ");
9610            sb.append(mLastFinishedFreezeSource);
9611        }
9612        Slog.i(TAG, sb.toString());
9613        mH.removeMessages(H.APP_FREEZE_TIMEOUT);
9614        mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
9615        if (PROFILE_ORIENTATION) {
9616            Debug.stopMethodTracing();
9617        }
9618
9619        boolean updateRotation = false;
9620
9621        final DisplayContent displayContent = getDefaultDisplayContentLocked();
9622        final int displayId = displayContent.getDisplayId();
9623        ScreenRotationAnimation screenRotationAnimation =
9624                mAnimator.getScreenRotationAnimationLocked(displayId);
9625        if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
9626                && screenRotationAnimation.hasScreenshot()) {
9627            if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation");
9628            // TODO(multidisplay): rotation on main screen only.
9629            DisplayInfo displayInfo = displayContent.getDisplayInfo();
9630            // Get rotation animation again, with new top window
9631            boolean isDimming = mAnimator.isDimmingLocked(Display.DEFAULT_DISPLAY);
9632            if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) {
9633                mExitAnimId = mEnterAnimId = 0;
9634            }
9635            if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
9636                    mTransitionAnimationScale, displayInfo.logicalWidth,
9637                        displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) {
9638                scheduleAnimationLocked();
9639            } else {
9640                screenRotationAnimation.kill();
9641                screenRotationAnimation = null;
9642                mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
9643                updateRotation = true;
9644            }
9645        } else {
9646            if (screenRotationAnimation != null) {
9647                screenRotationAnimation.kill();
9648                screenRotationAnimation = null;
9649                mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
9650            }
9651            updateRotation = true;
9652        }
9653
9654        mInputMonitor.thawInputDispatchingLw();
9655
9656        boolean configChanged;
9657
9658        // While the display is frozen we don't re-compute the orientation
9659        // to avoid inconsistent states.  However, something interesting
9660        // could have actually changed during that time so re-evaluate it
9661        // now to catch that.
9662        configChanged = updateOrientationFromAppTokensLocked(false);
9663
9664        // A little kludge: a lot could have happened while the
9665        // display was frozen, so now that we are coming back we
9666        // do a gc so that any remote references the system
9667        // processes holds on others can be released if they are
9668        // no longer needed.
9669        mH.removeMessages(H.FORCE_GC);
9670        mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000);
9671
9672        mScreenFrozenLock.release();
9673
9674        if (updateRotation) {
9675            if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
9676            configChanged |= updateRotationUncheckedLocked(false);
9677        }
9678
9679        if (configChanged) {
9680            mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
9681        }
9682    }
9683
9684    static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps,
9685            DisplayMetrics dm) {
9686        if (index < tokens.length) {
9687            String str = tokens[index];
9688            if (str != null && str.length() > 0) {
9689                try {
9690                    int val = Integer.parseInt(str);
9691                    return val;
9692                } catch (Exception e) {
9693                }
9694            }
9695        }
9696        if (defUnits == TypedValue.COMPLEX_UNIT_PX) {
9697            return defDps;
9698        }
9699        int val = (int)TypedValue.applyDimension(defUnits, defDps, dm);
9700        return val;
9701    }
9702
9703    void createWatermarkInTransaction() {
9704        if (mWatermark != null) {
9705            return;
9706        }
9707
9708        File file = new File("/system/etc/setup.conf");
9709        FileInputStream in = null;
9710        DataInputStream ind = null;
9711        try {
9712            in = new FileInputStream(file);
9713            ind = new DataInputStream(in);
9714            String line = ind.readLine();
9715            if (line != null) {
9716                String[] toks = line.split("%");
9717                if (toks != null && toks.length > 0) {
9718                    mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(),
9719                            mRealDisplayMetrics, mFxSession, toks);
9720                }
9721            }
9722        } catch (FileNotFoundException e) {
9723        } catch (IOException e) {
9724        } finally {
9725            if (ind != null) {
9726                try {
9727                    ind.close();
9728                } catch (IOException e) {
9729                }
9730            } else if (in != null) {
9731                try {
9732                    in.close();
9733                } catch (IOException e) {
9734                }
9735            }
9736        }
9737    }
9738
9739    @Override
9740    public void statusBarVisibilityChanged(int visibility) {
9741        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
9742                != PackageManager.PERMISSION_GRANTED) {
9743            throw new SecurityException("Caller does not hold permission "
9744                    + android.Manifest.permission.STATUS_BAR);
9745        }
9746
9747        synchronized (mWindowMap) {
9748            mLastStatusBarVisibility = visibility;
9749            visibility = mPolicy.adjustSystemUiVisibilityLw(visibility);
9750            updateStatusBarVisibilityLocked(visibility);
9751        }
9752    }
9753
9754    // TOOD(multidisplay): StatusBar on multiple screens?
9755    void updateStatusBarVisibilityLocked(int visibility) {
9756        mInputManager.setSystemUiVisibility(visibility);
9757        final WindowList windows = getDefaultWindowListLocked();
9758        final int N = windows.size();
9759        for (int i = 0; i < N; i++) {
9760            WindowState ws = windows.get(i);
9761            try {
9762                int curValue = ws.mSystemUiVisibility;
9763                int diff = curValue ^ visibility;
9764                // We are only interested in differences of one of the
9765                // clearable flags...
9766                diff &= View.SYSTEM_UI_CLEARABLE_FLAGS;
9767                // ...if it has actually been cleared.
9768                diff &= ~visibility;
9769                int newValue = (curValue&~diff) | (visibility&diff);
9770                if (newValue != curValue) {
9771                    ws.mSeq++;
9772                    ws.mSystemUiVisibility = newValue;
9773                }
9774                if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) {
9775                    ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq,
9776                            visibility, newValue, diff);
9777                }
9778            } catch (RemoteException e) {
9779                // so sorry
9780            }
9781        }
9782    }
9783
9784    @Override
9785    public void reevaluateStatusBarVisibility() {
9786        synchronized (mWindowMap) {
9787            int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility);
9788            updateStatusBarVisibilityLocked(visibility);
9789            performLayoutAndPlaceSurfacesLocked();
9790        }
9791    }
9792
9793    @Override
9794    public FakeWindow addFakeWindow(Looper looper,
9795            InputEventReceiver.Factory inputEventReceiverFactory,
9796            String name, int windowType, int layoutParamsFlags, boolean canReceiveKeys,
9797            boolean hasFocus, boolean touchFullscreen) {
9798        synchronized (mWindowMap) {
9799            FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputEventReceiverFactory,
9800                    name, windowType,
9801                    layoutParamsFlags, canReceiveKeys, hasFocus, touchFullscreen);
9802            int i=0;
9803            while (i<mFakeWindows.size()) {
9804                if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) {
9805                    break;
9806                }
9807            }
9808            mFakeWindows.add(i, fw);
9809            mInputMonitor.updateInputWindowsLw(true);
9810            return fw;
9811        }
9812    }
9813
9814    boolean removeFakeWindowLocked(FakeWindow window) {
9815        synchronized (mWindowMap) {
9816            if (mFakeWindows.remove(window)) {
9817                mInputMonitor.updateInputWindowsLw(true);
9818                return true;
9819            }
9820            return false;
9821        }
9822    }
9823
9824    // It is assumed that this method is called only by InputMethodManagerService.
9825    public void saveLastInputMethodWindowForTransition() {
9826        synchronized (mWindowMap) {
9827            // TODO(multidisplay): Pass in the displayID.
9828            DisplayContent displayContent = getDefaultDisplayContentLocked();
9829            if (mInputMethodWindow != null) {
9830                mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget);
9831            }
9832        }
9833    }
9834
9835    @Override
9836    public boolean hasNavigationBar() {
9837        return mPolicy.hasNavigationBar();
9838    }
9839
9840    @Override
9841    public void lockNow(Bundle options) {
9842        mPolicy.lockNow(options);
9843    }
9844
9845    @Override
9846    public boolean isSafeModeEnabled() {
9847        return mSafeMode;
9848    }
9849
9850    @Override
9851    public void showAssistant() {
9852        // TODO: What permission?
9853        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER)
9854                != PackageManager.PERMISSION_GRANTED) {
9855            return;
9856        }
9857        mPolicy.showAssistant();
9858    }
9859
9860    void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) {
9861        pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)");
9862        mPolicy.dump("    ", pw, args);
9863    }
9864
9865    void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) {
9866        pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)");
9867        mAnimator.dumpLocked(pw, "    ", dumpAll);
9868    }
9869
9870    void dumpTokensLocked(PrintWriter pw, boolean dumpAll) {
9871        pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)");
9872        if (mTokenMap.size() > 0) {
9873            pw.println("  All tokens:");
9874            Iterator<WindowToken> it = mTokenMap.values().iterator();
9875            while (it.hasNext()) {
9876                WindowToken token = it.next();
9877                pw.print("  "); pw.print(token);
9878                if (dumpAll) {
9879                    pw.println(':');
9880                    token.dump(pw, "    ");
9881                } else {
9882                    pw.println();
9883                }
9884            }
9885        }
9886        if (mWallpaperTokens.size() > 0) {
9887            pw.println();
9888            pw.println("  Wallpaper tokens:");
9889            for (int i=mWallpaperTokens.size()-1; i>=0; i--) {
9890                WindowToken token = mWallpaperTokens.get(i);
9891                pw.print("  Wallpaper #"); pw.print(i);
9892                        pw.print(' '); pw.print(token);
9893                if (dumpAll) {
9894                    pw.println(':');
9895                    token.dump(pw, "    ");
9896                } else {
9897                    pw.println();
9898                }
9899            }
9900        }
9901        if (mAppTokens.size() > 0) {
9902            pw.println();
9903            pw.println("  Application tokens in Z order:");
9904            for (int i=mAppTokens.size()-1; i>=0; i--) {
9905                pw.print("  App #"); pw.print(i);
9906                        pw.print(' '); pw.print(mAppTokens.get(i)); pw.println(":");
9907                mAppTokens.get(i).dump(pw, "    ");
9908            }
9909        }
9910        if (mFinishedStarting.size() > 0) {
9911            pw.println();
9912            pw.println("  Finishing start of application tokens:");
9913            for (int i=mFinishedStarting.size()-1; i>=0; i--) {
9914                WindowToken token = mFinishedStarting.get(i);
9915                pw.print("  Finished Starting #"); pw.print(i);
9916                        pw.print(' '); pw.print(token);
9917                if (dumpAll) {
9918                    pw.println(':');
9919                    token.dump(pw, "    ");
9920                } else {
9921                    pw.println();
9922                }
9923            }
9924        }
9925        if (mExitingTokens.size() > 0) {
9926            pw.println();
9927            pw.println("  Exiting tokens:");
9928            for (int i=mExitingTokens.size()-1; i>=0; i--) {
9929                WindowToken token = mExitingTokens.get(i);
9930                pw.print("  Exiting #"); pw.print(i);
9931                        pw.print(' '); pw.print(token);
9932                if (dumpAll) {
9933                    pw.println(':');
9934                    token.dump(pw, "    ");
9935                } else {
9936                    pw.println();
9937                }
9938            }
9939        }
9940        if (mExitingAppTokens.size() > 0) {
9941            pw.println();
9942            pw.println("  Exiting application tokens:");
9943            for (int i=mExitingAppTokens.size()-1; i>=0; i--) {
9944                WindowToken token = mExitingAppTokens.get(i);
9945                pw.print("  Exiting App #"); pw.print(i);
9946                        pw.print(' '); pw.print(token);
9947                if (dumpAll) {
9948                    pw.println(':');
9949                    token.dump(pw, "    ");
9950                } else {
9951                    pw.println();
9952                }
9953            }
9954        }
9955        if (mAppTransition.isRunning() && mAnimatingAppTokens.size() > 0) {
9956            pw.println();
9957            pw.println("  Application tokens during animation:");
9958            for (int i=mAnimatingAppTokens.size()-1; i>=0; i--) {
9959                WindowToken token = mAnimatingAppTokens.get(i);
9960                pw.print("  App moving to bottom #"); pw.print(i);
9961                        pw.print(' '); pw.print(token);
9962                if (dumpAll) {
9963                    pw.println(':');
9964                    token.dump(pw, "    ");
9965                } else {
9966                    pw.println();
9967                }
9968            }
9969        }
9970        if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) {
9971            pw.println();
9972            if (mOpeningApps.size() > 0) {
9973                pw.print("  mOpeningApps="); pw.println(mOpeningApps);
9974            }
9975            if (mClosingApps.size() > 0) {
9976                pw.print("  mClosingApps="); pw.println(mClosingApps);
9977            }
9978        }
9979    }
9980
9981    void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) {
9982        pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)");
9983        if (mSessions.size() > 0) {
9984            Iterator<Session> it = mSessions.iterator();
9985            while (it.hasNext()) {
9986                Session s = it.next();
9987                pw.print("  Session "); pw.print(s); pw.println(':');
9988                s.dump(pw, "    ");
9989            }
9990        }
9991    }
9992
9993    void dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll) {
9994        pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)");
9995        if (mDisplayReady) {
9996            DisplayContentsIterator dCIterator = new DisplayContentsIterator();
9997            while (dCIterator.hasNext()) {
9998                dCIterator.next().dump("  ", pw);
9999            }
10000        } else {
10001            pw.println("  NO DISPLAY");
10002        }
10003    }
10004
10005    void dumpWindowsLocked(PrintWriter pw, boolean dumpAll,
10006            ArrayList<WindowState> windows) {
10007        pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)");
10008        dumpWindowsNoHeaderLocked(pw, dumpAll, windows);
10009    }
10010
10011    void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll,
10012            ArrayList<WindowState> windows) {
10013        int j = 0;
10014        final AllWindowsIterator iterator = new AllWindowsIterator(REVERSE_ITERATOR);
10015        while (iterator.hasNext()) {
10016            final WindowState w = iterator.next();
10017            if (windows == null || windows.contains(w)) {
10018                pw.print("  Window #"); pw.print(j++); pw.print(' ');
10019                        pw.print(w); pw.println(":");
10020                w.dump(pw, "    ", dumpAll || windows != null);
10021            }
10022        }
10023        if (mInputMethodDialogs.size() > 0) {
10024            pw.println();
10025            pw.println("  Input method dialogs:");
10026            for (int i=mInputMethodDialogs.size()-1; i>=0; i--) {
10027                WindowState w = mInputMethodDialogs.get(i);
10028                if (windows == null || windows.contains(w)) {
10029                    pw.print("  IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w);
10030                }
10031            }
10032        }
10033        if (mPendingRemove.size() > 0) {
10034            pw.println();
10035            pw.println("  Remove pending for:");
10036            for (int i=mPendingRemove.size()-1; i>=0; i--) {
10037                WindowState w = mPendingRemove.get(i);
10038                if (windows == null || windows.contains(w)) {
10039                    pw.print("  Remove #"); pw.print(i); pw.print(' ');
10040                            pw.print(w);
10041                    if (dumpAll) {
10042                        pw.println(":");
10043                        w.dump(pw, "    ", true);
10044                    } else {
10045                        pw.println();
10046                    }
10047                }
10048            }
10049        }
10050        if (mForceRemoves != null && mForceRemoves.size() > 0) {
10051            pw.println();
10052            pw.println("  Windows force removing:");
10053            for (int i=mForceRemoves.size()-1; i>=0; i--) {
10054                WindowState w = mForceRemoves.get(i);
10055                pw.print("  Removing #"); 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        if (mDestroySurface.size() > 0) {
10066            pw.println();
10067            pw.println("  Windows waiting to destroy their surface:");
10068            for (int i=mDestroySurface.size()-1; i>=0; i--) {
10069                WindowState w = mDestroySurface.get(i);
10070                if (windows == null || windows.contains(w)) {
10071                    pw.print("  Destroy #"); pw.print(i); pw.print(' ');
10072                            pw.print(w);
10073                    if (dumpAll) {
10074                        pw.println(":");
10075                        w.dump(pw, "    ", true);
10076                    } else {
10077                        pw.println();
10078                    }
10079                }
10080            }
10081        }
10082        if (mLosingFocus.size() > 0) {
10083            pw.println();
10084            pw.println("  Windows losing focus:");
10085            for (int i=mLosingFocus.size()-1; i>=0; i--) {
10086                WindowState w = mLosingFocus.get(i);
10087                if (windows == null || windows.contains(w)) {
10088                    pw.print("  Losing #"); pw.print(i); pw.print(' ');
10089                            pw.print(w);
10090                    if (dumpAll) {
10091                        pw.println(":");
10092                        w.dump(pw, "    ", true);
10093                    } else {
10094                        pw.println();
10095                    }
10096                }
10097            }
10098        }
10099        if (mResizingWindows.size() > 0) {
10100            pw.println();
10101            pw.println("  Windows waiting to resize:");
10102            for (int i=mResizingWindows.size()-1; i>=0; i--) {
10103                WindowState w = mResizingWindows.get(i);
10104                if (windows == null || windows.contains(w)) {
10105                    pw.print("  Resizing #"); pw.print(i); pw.print(' ');
10106                            pw.print(w);
10107                    if (dumpAll) {
10108                        pw.println(":");
10109                        w.dump(pw, "    ", true);
10110                    } else {
10111                        pw.println();
10112                    }
10113                }
10114            }
10115        }
10116        if (mWaitingForDrawn.size() > 0) {
10117            pw.println();
10118            pw.println("  Clients waiting for these windows to be drawn:");
10119            for (int i=mWaitingForDrawn.size()-1; i>=0; i--) {
10120                Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(i);
10121                pw.print("  Waiting #"); pw.print(i); pw.print(' '); pw.print(pair.first);
10122                        pw.print(": "); pw.println(pair.second);
10123            }
10124        }
10125        pw.println();
10126        pw.print("  mCurConfiguration="); pw.println(this.mCurConfiguration);
10127        pw.print("  mCurrentFocus="); pw.println(mCurrentFocus);
10128        if (mLastFocus != mCurrentFocus) {
10129            pw.print("  mLastFocus="); pw.println(mLastFocus);
10130        }
10131        pw.print("  mFocusedApp="); pw.println(mFocusedApp);
10132        if (mInputMethodTarget != null) {
10133            pw.print("  mInputMethodTarget="); pw.println(mInputMethodTarget);
10134        }
10135        pw.print("  mInTouchMode="); pw.print(mInTouchMode);
10136                pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
10137        pw.print("  mLastDisplayFreezeDuration=");
10138                TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw);
10139                if ( mLastFinishedFreezeSource != null) {
10140                    pw.print(" due to ");
10141                    pw.print(mLastFinishedFreezeSource);
10142                }
10143                pw.println();
10144        if (dumpAll) {
10145            pw.print("  mSystemDecorRect="); pw.print(mSystemDecorRect.toShortString());
10146                    pw.print(" mSystemDecorLayer="); pw.print(mSystemDecorLayer);
10147                    pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString());
10148            if (mLastStatusBarVisibility != 0) {
10149                pw.print("  mLastStatusBarVisibility=0x");
10150                        pw.println(Integer.toHexString(mLastStatusBarVisibility));
10151            }
10152            if (mInputMethodWindow != null) {
10153                pw.print("  mInputMethodWindow="); pw.println(mInputMethodWindow);
10154            }
10155            pw.print("  mWallpaperTarget="); pw.println(mWallpaperTarget);
10156            if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) {
10157                pw.print("  mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget);
10158                pw.print("  mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget);
10159            }
10160            pw.print("  mLastWallpaperX="); pw.print(mLastWallpaperX);
10161                    pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
10162            if (mInputMethodAnimLayerAdjustment != 0 ||
10163                    mWallpaperAnimLayerAdjustment != 0) {
10164                pw.print("  mInputMethodAnimLayerAdjustment=");
10165                        pw.print(mInputMethodAnimLayerAdjustment);
10166                        pw.print("  mWallpaperAnimLayerAdjustment=");
10167                        pw.println(mWallpaperAnimLayerAdjustment);
10168            }
10169            pw.print("  mSystemBooted="); pw.print(mSystemBooted);
10170                    pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
10171            if (needsLayout()) {
10172                pw.print("  layoutNeeded on displays=");
10173                DisplayContentsIterator dcIterator = new DisplayContentsIterator();
10174                while (dcIterator.hasNext()) {
10175                    final DisplayContent displayContent = dcIterator.next();
10176                    if (displayContent.layoutNeeded) {
10177                        pw.print(displayContent.getDisplayId());
10178                    }
10179                }
10180                pw.println();
10181            }
10182            pw.print("  mTransactionSequence="); pw.println(mTransactionSequence);
10183            pw.print("  mDisplayFrozen="); pw.print(mDisplayFrozen);
10184                    pw.print(" windows="); pw.print(mWindowsFreezingScreen);
10185                    pw.print(" client="); pw.print(mClientFreezingScreen);
10186                    pw.print(" apps="); pw.print(mAppsFreezingScreen);
10187                    pw.print(" waitingForConfig="); pw.println(mWaitingForConfig);
10188            pw.print("  mRotation="); pw.print(mRotation);
10189                    pw.print(" mAltOrientation="); pw.println(mAltOrientation);
10190            pw.print("  mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation);
10191                    pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation);
10192            pw.print("  mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount);
10193            pw.print("  mWindowAnimationScale="); pw.print(mWindowAnimationScale);
10194                    pw.print(" mTransitionWindowAnimationScale="); pw.print(mTransitionAnimationScale);
10195                    pw.print(" mAnimatorDurationScale="); pw.println(mAnimatorDurationScale);
10196            pw.print("  mTraversalScheduled="); pw.println(mTraversalScheduled);
10197            pw.print("  mStartingIconInTransition="); pw.print(mStartingIconInTransition);
10198                    pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
10199            pw.println("  mLayoutToAnim:");
10200            mAppTransition.dump(pw);
10201        }
10202    }
10203
10204    boolean dumpWindows(PrintWriter pw, String name, String[] args,
10205            int opti, boolean dumpAll) {
10206        WindowList windows = new WindowList();
10207        if ("visible".equals(name)) {
10208            synchronized(mWindowMap) {
10209                final AllWindowsIterator iterator = new AllWindowsIterator(REVERSE_ITERATOR);
10210                while (iterator.hasNext()) {
10211                    final WindowState w = iterator.next();
10212                    if (w.mWinAnimator.mSurfaceShown) {
10213                        windows.add(w);
10214                    }
10215                }
10216            }
10217        } else {
10218            int objectId = 0;
10219            // See if this is an object ID.
10220            try {
10221                objectId = Integer.parseInt(name, 16);
10222                name = null;
10223            } catch (RuntimeException e) {
10224            }
10225            synchronized(mWindowMap) {
10226                final AllWindowsIterator iterator = new AllWindowsIterator(REVERSE_ITERATOR);
10227                while (iterator.hasNext()) {
10228                    final WindowState w = iterator.next();
10229                    if (name != null) {
10230                        if (w.mAttrs.getTitle().toString().contains(name)) {
10231                            windows.add(w);
10232                        }
10233                    } else if (System.identityHashCode(w) == objectId) {
10234                        windows.add(w);
10235                    }
10236                }
10237            }
10238        }
10239
10240        if (windows.size() <= 0) {
10241            return false;
10242        }
10243
10244        synchronized(mWindowMap) {
10245            dumpWindowsLocked(pw, dumpAll, windows);
10246        }
10247        return true;
10248    }
10249
10250    void dumpLastANRLocked(PrintWriter pw) {
10251        pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)");
10252        if (mLastANRState == null) {
10253            pw.println("  <no ANR has occurred since boot>");
10254        } else {
10255            pw.println(mLastANRState);
10256        }
10257    }
10258
10259    /**
10260     * Saves information about the state of the window manager at
10261     * the time an ANR occurred before anything else in the system changes
10262     * in response.
10263     *
10264     * @param appWindowToken The application that ANR'd, may be null.
10265     * @param windowState The window that ANR'd, may be null.
10266     */
10267    public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState) {
10268        StringWriter sw = new StringWriter();
10269        PrintWriter pw = new PrintWriter(sw);
10270        pw.println("  ANR time: " + DateFormat.getInstance().format(new Date()));
10271        if (appWindowToken != null) {
10272            pw.println("  Application at fault: " + appWindowToken.stringName);
10273        }
10274        if (windowState != null) {
10275            pw.println("  Window at fault: " + windowState.mAttrs.getTitle());
10276        }
10277        pw.println();
10278        dumpWindowsNoHeaderLocked(pw, true, null);
10279        pw.close();
10280        mLastANRState = sw.toString();
10281    }
10282
10283    @Override
10284    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
10285        if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
10286                != PackageManager.PERMISSION_GRANTED) {
10287            pw.println("Permission Denial: can't dump WindowManager from from pid="
10288                    + Binder.getCallingPid()
10289                    + ", uid=" + Binder.getCallingUid());
10290            return;
10291        }
10292
10293        boolean dumpAll = false;
10294
10295        int opti = 0;
10296        while (opti < args.length) {
10297            String opt = args[opti];
10298            if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
10299                break;
10300            }
10301            opti++;
10302            if ("-a".equals(opt)) {
10303                dumpAll = true;
10304            } else if ("-h".equals(opt)) {
10305                pw.println("Window manager dump options:");
10306                pw.println("  [-a] [-h] [cmd] ...");
10307                pw.println("  cmd may be one of:");
10308                pw.println("    l[astanr]: last ANR information");
10309                pw.println("    p[policy]: policy state");
10310                pw.println("    a[animator]: animator state");
10311                pw.println("    s[essions]: active sessions");
10312                pw.println("    d[isplays]: active display contents");
10313                pw.println("    t[okens]: token list");
10314                pw.println("    w[indows]: window list");
10315                pw.println("  cmd may also be a NAME to dump windows.  NAME may");
10316                pw.println("    be a partial substring in a window name, a");
10317                pw.println("    Window hex object identifier, or");
10318                pw.println("    \"all\" for all windows, or");
10319                pw.println("    \"visible\" for the visible windows.");
10320                pw.println("  -a: include all available server state.");
10321                return;
10322            } else {
10323                pw.println("Unknown argument: " + opt + "; use -h for help");
10324            }
10325        }
10326
10327        // Is the caller requesting to dump a particular piece of data?
10328        if (opti < args.length) {
10329            String cmd = args[opti];
10330            opti++;
10331            if ("lastanr".equals(cmd) || "l".equals(cmd)) {
10332                synchronized(mWindowMap) {
10333                    dumpLastANRLocked(pw);
10334                }
10335                return;
10336            } else if ("policy".equals(cmd) || "p".equals(cmd)) {
10337                synchronized(mWindowMap) {
10338                    dumpPolicyLocked(pw, args, true);
10339                }
10340                return;
10341            } else if ("animator".equals(cmd) || "a".equals(cmd)) {
10342                synchronized(mWindowMap) {
10343                    dumpAnimatorLocked(pw, args, true);
10344                }
10345                return;
10346            } else if ("sessions".equals(cmd) || "s".equals(cmd)) {
10347                synchronized(mWindowMap) {
10348                    dumpSessionsLocked(pw, true);
10349                }
10350                return;
10351            } else if ("displays".equals(cmd) || "d".equals(cmd)) {
10352                synchronized(mWindowMap) {
10353                    dumpDisplayContentsLocked(pw, true);
10354                }
10355                return;
10356            } else if ("tokens".equals(cmd) || "t".equals(cmd)) {
10357                synchronized(mWindowMap) {
10358                    dumpTokensLocked(pw, true);
10359                }
10360                return;
10361            } else if ("windows".equals(cmd) || "w".equals(cmd)) {
10362                synchronized(mWindowMap) {
10363                    dumpWindowsLocked(pw, true, null);
10364                }
10365                return;
10366            } else if ("all".equals(cmd) || "a".equals(cmd)) {
10367                synchronized(mWindowMap) {
10368                    dumpWindowsLocked(pw, true, null);
10369                }
10370                return;
10371            } else {
10372                // Dumping a single name?
10373                if (!dumpWindows(pw, cmd, args, opti, dumpAll)) {
10374                    pw.println("Bad window command, or no windows match: " + cmd);
10375                    pw.println("Use -h for help.");
10376                }
10377                return;
10378            }
10379        }
10380
10381        synchronized(mWindowMap) {
10382            pw.println();
10383            if (dumpAll) {
10384                pw.println("-------------------------------------------------------------------------------");
10385            }
10386            dumpLastANRLocked(pw);
10387            pw.println();
10388            if (dumpAll) {
10389                pw.println("-------------------------------------------------------------------------------");
10390            }
10391            dumpPolicyLocked(pw, args, dumpAll);
10392            pw.println();
10393            if (dumpAll) {
10394                pw.println("-------------------------------------------------------------------------------");
10395            }
10396            dumpAnimatorLocked(pw, args, dumpAll);
10397            pw.println();
10398            if (dumpAll) {
10399                pw.println("-------------------------------------------------------------------------------");
10400            }
10401            dumpSessionsLocked(pw, dumpAll);
10402            pw.println();
10403            if (dumpAll) {
10404                pw.println("-------------------------------------------------------------------------------");
10405            }
10406            dumpDisplayContentsLocked(pw, dumpAll);
10407            pw.println();
10408            if (dumpAll) {
10409                pw.println("-------------------------------------------------------------------------------");
10410            }
10411            dumpTokensLocked(pw, dumpAll);
10412            pw.println();
10413            if (dumpAll) {
10414                pw.println("-------------------------------------------------------------------------------");
10415            }
10416            dumpWindowsLocked(pw, dumpAll, null);
10417        }
10418    }
10419
10420    // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection).
10421    @Override
10422    public void monitor() {
10423        synchronized (mWindowMap) { }
10424    }
10425
10426    public interface OnHardKeyboardStatusChangeListener {
10427        public void onHardKeyboardStatusChange(boolean available, boolean enabled);
10428    }
10429
10430    void debugLayoutRepeats(final String msg, int pendingLayoutChanges) {
10431        if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) {
10432            Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" +
10433                    Integer.toHexString(pendingLayoutChanges));
10434        }
10435    }
10436
10437    private DisplayContent newDisplayContentLocked(final Display display) {
10438        DisplayContent displayContent = new DisplayContent(display);
10439        mDisplayContents.put(display.getDisplayId(), displayContent);
10440        final Rect rect = new Rect();
10441        DisplayInfo info = displayContent.getDisplayInfo();
10442        mDisplaySettings.getOverscanLocked(info.name, rect);
10443        info.overscanLeft = rect.left;
10444        info.overscanTop = rect.top;
10445        info.overscanRight = rect.right;
10446        info.overscanBottom = rect.bottom;
10447        mDisplayManagerService.setOverscan(display.getDisplayId(), rect.left, rect.top,
10448                rect.right, rect.bottom);
10449        mPolicy.setDisplayOverscan(displayContent.getDisplay(), rect.left, rect.top,
10450                rect.right, rect.bottom);
10451        return displayContent;
10452    }
10453
10454    public void createDisplayContentLocked(final Display display) {
10455        if (display == null) {
10456            throw new IllegalArgumentException("getDisplayContent: display must not be null");
10457        }
10458        newDisplayContentLocked(display);
10459    }
10460
10461    /**
10462     * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if
10463     * there is a Display for the displayId.
10464     * @param displayId The display the caller is interested in.
10465     * @return The DisplayContent associated with displayId or null if there is no Display for it.
10466     */
10467    public DisplayContent getDisplayContentLocked(final int displayId) {
10468        DisplayContent displayContent = mDisplayContents.get(displayId);
10469        if (displayContent == null) {
10470            final Display display = mDisplayManager.getDisplay(displayId);
10471            if (display != null) {
10472                displayContent = newDisplayContentLocked(display);
10473            }
10474        }
10475        return displayContent;
10476    }
10477
10478    class DisplayContentsIterator implements Iterator<DisplayContent> {
10479        private int cur;
10480
10481        @Override
10482        public boolean hasNext() {
10483            return cur < mDisplayContents.size();
10484        }
10485
10486        @Override
10487        public DisplayContent next() {
10488            if (hasNext()) {
10489                return mDisplayContents.valueAt(cur++);
10490            }
10491            throw new NoSuchElementException();
10492        }
10493
10494        @Override
10495        public void remove() {
10496            throw new IllegalArgumentException("AllDisplayContentIterator.remove not implemented");
10497        }
10498    }
10499
10500    final static boolean REVERSE_ITERATOR = true;
10501    class AllWindowsIterator implements Iterator<WindowState> {
10502        private DisplayContent mDisplayContent;
10503        private DisplayContentsIterator mDisplayContentsIterator;
10504        private WindowList mWindowList;
10505        private int mWindowListIndex;
10506        private boolean mReverse;
10507
10508        AllWindowsIterator() {
10509            mDisplayContentsIterator = new DisplayContentsIterator();
10510            mDisplayContent = mDisplayContentsIterator.next();
10511            mWindowList = mDisplayContent.getWindowList();
10512        }
10513
10514        AllWindowsIterator(boolean reverse) {
10515            this();
10516            mReverse = reverse;
10517            mWindowListIndex = reverse ? mWindowList.size() - 1 : 0;
10518        }
10519
10520        @Override
10521        public boolean hasNext() {
10522            if (mReverse) {
10523                return mWindowListIndex >= 0;
10524            }
10525            return mWindowListIndex < mWindowList.size();
10526        }
10527
10528        @Override
10529        public WindowState next() {
10530            if (hasNext()) {
10531                WindowState win = mWindowList.get(mWindowListIndex);
10532                if (mReverse) {
10533                    mWindowListIndex--;
10534                    if (mWindowListIndex < 0 && mDisplayContentsIterator.hasNext()) {
10535                        mDisplayContent = mDisplayContentsIterator.next();
10536                        mWindowList = mDisplayContent.getWindowList();
10537                        mWindowListIndex = mWindowList.size() - 1;
10538                    }
10539                } else {
10540                    mWindowListIndex++;
10541                    if (mWindowListIndex >= mWindowList.size()
10542                            && mDisplayContentsIterator.hasNext()) {
10543                        mDisplayContent = mDisplayContentsIterator.next();
10544                        mWindowList = mDisplayContent.getWindowList();
10545                        mWindowListIndex = 0;
10546                    }
10547                }
10548                return win;
10549            }
10550            throw new NoSuchElementException();
10551        }
10552
10553        @Override
10554        public void remove() {
10555            throw new IllegalArgumentException("AllWindowsIterator.remove not implemented");
10556        }
10557    }
10558
10559    // There is an inherent assumption that this will never return null.
10560    public DisplayContent getDefaultDisplayContentLocked() {
10561        return getDisplayContentLocked(Display.DEFAULT_DISPLAY);
10562    }
10563
10564    public WindowList getDefaultWindowListLocked() {
10565        return getDefaultDisplayContentLocked().getWindowList();
10566    }
10567
10568    public DisplayInfo getDefaultDisplayInfoLocked() {
10569        return getDefaultDisplayContentLocked().getDisplayInfo();
10570    }
10571
10572    /**
10573     * Return the list of WindowStates associated on the passed display.
10574     * @param display The screen to return windows from.
10575     * @return The list of WindowStates on the screen, or null if the there is no screen.
10576     */
10577    public WindowList getWindowListLocked(final Display display) {
10578        return getWindowListLocked(display.getDisplayId());
10579    }
10580
10581    /**
10582     * Return the list of WindowStates associated on the passed display.
10583     * @param displayId The screen to return windows from.
10584     * @return The list of WindowStates on the screen, or null if the there is no screen.
10585     */
10586    public WindowList getWindowListLocked(final int displayId) {
10587        final DisplayContent displayContent = getDisplayContentLocked(displayId);
10588        return displayContent != null ? displayContent.getWindowList() : null;
10589    }
10590
10591    @Override
10592    public void onDisplayAdded(int displayId) {
10593        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0));
10594    }
10595
10596    private void handleDisplayAddedLocked(int displayId) {
10597        final Display display = mDisplayManager.getDisplay(displayId);
10598        if (display != null) {
10599            createDisplayContentLocked(display);
10600            displayReady(displayId);
10601        }
10602    }
10603
10604    @Override
10605    public void onDisplayRemoved(int displayId) {
10606        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0));
10607    }
10608
10609    private void handleDisplayRemovedLocked(int displayId) {
10610        final DisplayContent displayContent = getDisplayContentLocked(displayId);
10611        if (displayContent != null) {
10612            mDisplayContents.delete(displayId);
10613            WindowList windows = displayContent.getWindowList();
10614            while (!windows.isEmpty()) {
10615                final WindowState win = windows.get(windows.size() - 1);
10616                removeWindowLocked(win.mSession, win);
10617            }
10618        }
10619        mAnimator.removeDisplayLocked(displayId);
10620    }
10621
10622    @Override
10623    public void onDisplayChanged(int displayId) {
10624        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0));
10625    }
10626
10627    private void handleDisplayChangedLocked(int displayId) {
10628        final DisplayContent displayContent = getDisplayContentLocked(displayId);
10629        if (displayContent != null) {
10630            displayContent.updateDisplayInfo();
10631        }
10632    }
10633}
10634