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