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