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