Explode WindowManagerService.

Change-Id: I3d73ed4c9a1b5d730aeffeb2df24ce5e6117d698
diff --git a/services/java/com/android/server/wm/AppWindowToken.java b/services/java/com/android/server/wm/AppWindowToken.java
new file mode 100644
index 0000000..d3d9df4
--- /dev/null
+++ b/services/java/com/android/server/wm/AppWindowToken.java
@@ -0,0 +1,413 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+
+import com.android.server.wm.WindowManagerService.H;
+
+import android.content.pm.ActivityInfo;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.Slog;
+import android.view.IApplicationToken;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.animation.Animation;
+import android.view.animation.Transformation;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+/**
+ * Version of WindowToken that is specifically for a particular application (or
+ * really activity) that is displaying windows.
+ */
+class AppWindowToken extends WindowToken {
+    // Non-null only for application tokens.
+    final IApplicationToken appToken;
+
+    // All of the windows and child windows that are included in this
+    // application token.  Note this list is NOT sorted!
+    final ArrayList<WindowState> allAppWindows = new ArrayList<WindowState>();
+
+    int groupId = -1;
+    boolean appFullscreen;
+    int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+    
+    // The input dispatching timeout for this application token in nanoseconds.
+    long inputDispatchingTimeoutNanos;
+
+    // These are used for determining when all windows associated with
+    // an activity have been drawn, so they can be made visible together
+    // at the same time.
+    int lastTransactionSequence;
+    int numInterestingWindows;
+    int numDrawnWindows;
+    boolean inPendingTransaction;
+    boolean allDrawn;
+
+    // Is this token going to be hidden in a little while?  If so, it
+    // won't be taken into account for setting the screen orientation.
+    boolean willBeHidden;
+
+    // Is this window's surface needed?  This is almost like hidden, except
+    // it will sometimes be true a little earlier: when the token has
+    // been shown, but is still waiting for its app transition to execute
+    // before making its windows shown.
+    boolean hiddenRequested;
+
+    // Have we told the window clients to hide themselves?
+    boolean clientHidden;
+
+    // Last visibility state we reported to the app token.
+    boolean reportedVisible;
+
+    // Set to true when the token has been removed from the window mgr.
+    boolean removed;
+
+    // Have we been asked to have this token keep the screen frozen?
+    boolean freezingScreen;
+
+    boolean animating;
+    Animation animation;
+    boolean hasTransformation;
+    final Transformation transformation = new Transformation();
+
+    // Offset to the window of all layers in the token, for use by
+    // AppWindowToken animations.
+    int animLayerAdjustment;
+
+    // Information about an application starting window if displayed.
+    StartingData startingData;
+    WindowState startingWindow;
+    View startingView;
+    boolean startingDisplayed;
+    boolean startingMoved;
+    boolean firstWindowDrawn;
+
+    // Input application handle used by the input dispatcher.
+    InputApplicationHandle mInputApplicationHandle;
+
+    AppWindowToken(WindowManagerService _service, IApplicationToken _token) {
+        super(_service, _token.asBinder(),
+                WindowManager.LayoutParams.TYPE_APPLICATION, true);
+        appWindowToken = this;
+        appToken = _token;
+        mInputApplicationHandle = new InputApplicationHandle(this);
+        lastTransactionSequence = service.mTransactionSequence-1;
+    }
+
+    public void setAnimation(Animation anim) {
+        if (WindowManagerService.localLOGV) Slog.v(
+            WindowManagerService.TAG, "Setting animation in " + this + ": " + anim);
+        animation = anim;
+        animating = false;
+        anim.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION);
+        anim.scaleCurrentDuration(service.mTransitionAnimationScale);
+        int zorder = anim.getZAdjustment();
+        int adj = 0;
+        if (zorder == Animation.ZORDER_TOP) {
+            adj = WindowManagerService.TYPE_LAYER_OFFSET;
+        } else if (zorder == Animation.ZORDER_BOTTOM) {
+            adj = -WindowManagerService.TYPE_LAYER_OFFSET;
+        }
+
+        if (animLayerAdjustment != adj) {
+            animLayerAdjustment = adj;
+            updateLayers();
+        }
+    }
+
+    public void setDummyAnimation() {
+        if (animation == null) {
+            if (WindowManagerService.localLOGV) Slog.v(
+                WindowManagerService.TAG, "Setting dummy animation in " + this);
+            animation = WindowManagerService.sDummyAnimation;
+        }
+    }
+
+    public void clearAnimation() {
+        if (animation != null) {
+            animation = null;
+            animating = true;
+        }
+    }
+
+    void updateLayers() {
+        final int N = allAppWindows.size();
+        final int adj = animLayerAdjustment;
+        for (int i=0; i<N; i++) {
+            WindowState w = allAppWindows.get(i);
+            w.mAnimLayer = w.mLayer + adj;
+            if (WindowManagerService.DEBUG_LAYERS) Slog.v(WindowManagerService.TAG, "Updating layer " + w + ": "
+                    + w.mAnimLayer);
+            if (w == service.mInputMethodTarget && !service.mInputMethodTargetWaitingAnim) {
+                service.setInputMethodAnimLayerAdjustment(adj);
+            }
+            if (w == service.mWallpaperTarget && service.mLowerWallpaperTarget == null) {
+                service.setWallpaperAnimLayerAdjustmentLocked(adj);
+            }
+        }
+    }
+
+    void sendAppVisibilityToClients() {
+        final int N = allAppWindows.size();
+        for (int i=0; i<N; i++) {
+            WindowState win = allAppWindows.get(i);
+            if (win == startingWindow && clientHidden) {
+                // Don't hide the starting window.
+                continue;
+            }
+            try {
+                if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG,
+                        "Setting visibility of " + win + ": " + (!clientHidden));
+                win.mClient.dispatchAppVisibility(!clientHidden);
+            } catch (RemoteException e) {
+            }
+        }
+    }
+
+    void showAllWindowsLocked() {
+        final int NW = allAppWindows.size();
+        for (int i=0; i<NW; i++) {
+            WindowState w = allAppWindows.get(i);
+            if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG,
+                    "performing show on: " + w);
+            w.performShowLocked();
+        }
+    }
+
+    // This must be called while inside a transaction.
+    boolean stepAnimationLocked(long currentTime, int dw, int dh) {
+        if (!service.mDisplayFrozen && service.mPolicy.isScreenOn()) {
+            // We will run animations as long as the display isn't frozen.
+
+            if (animation == WindowManagerService.sDummyAnimation) {
+                // This guy is going to animate, but not yet.  For now count
+                // it as not animating for purposes of scheduling transactions;
+                // when it is really time to animate, this will be set to
+                // a real animation and the next call will execute normally.
+                return false;
+            }
+
+            if ((allDrawn || animating || startingDisplayed) && animation != null) {
+                if (!animating) {
+                    if (WindowManagerService.DEBUG_ANIM) Slog.v(
+                        WindowManagerService.TAG, "Starting animation in " + this +
+                        " @ " + currentTime + ": dw=" + dw + " dh=" + dh
+                        + " scale=" + service.mTransitionAnimationScale
+                        + " allDrawn=" + allDrawn + " animating=" + animating);
+                    animation.initialize(dw, dh, dw, dh);
+                    animation.setStartTime(currentTime);
+                    animating = true;
+                }
+                transformation.clear();
+                final boolean more = animation.getTransformation(
+                    currentTime, transformation);
+                if (WindowManagerService.DEBUG_ANIM) Slog.v(
+                    WindowManagerService.TAG, "Stepped animation in " + this +
+                    ": more=" + more + ", xform=" + transformation);
+                if (more) {
+                    // we're done!
+                    hasTransformation = true;
+                    return true;
+                }
+                if (WindowManagerService.DEBUG_ANIM) Slog.v(
+                    WindowManagerService.TAG, "Finished animation in " + this +
+                    " @ " + currentTime);
+                animation = null;
+            }
+        } else if (animation != null) {
+            // If the display is frozen, and there is a pending animation,
+            // clear it and make sure we run the cleanup code.
+            animating = true;
+            animation = null;
+        }
+
+        hasTransformation = false;
+
+        if (!animating) {
+            return false;
+        }
+
+        clearAnimation();
+        animating = false;
+        if (animLayerAdjustment != 0) {
+            animLayerAdjustment = 0;
+            updateLayers();
+        }
+        if (service.mInputMethodTarget != null && service.mInputMethodTarget.mAppToken == this) {
+            service.moveInputMethodWindowsIfNeededLocked(true);
+        }
+
+        if (WindowManagerService.DEBUG_ANIM) Slog.v(
+                WindowManagerService.TAG, "Animation done in " + this
+                + ": reportedVisible=" + reportedVisible);
+
+        transformation.clear();
+
+        final int N = windows.size();
+        for (int i=0; i<N; i++) {
+            windows.get(i).finishExit();
+        }
+        updateReportedVisibilityLocked();
+
+        return false;
+    }
+
+    void updateReportedVisibilityLocked() {
+        if (appToken == null) {
+            return;
+        }
+
+        int numInteresting = 0;
+        int numVisible = 0;
+        boolean nowGone = true;
+
+        if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "Update reported visibility: " + this);
+        final int N = allAppWindows.size();
+        for (int i=0; i<N; i++) {
+            WindowState win = allAppWindows.get(i);
+            if (win == startingWindow || win.mAppFreezing
+                    || win.mViewVisibility != View.VISIBLE
+                    || win.mAttrs.type == TYPE_APPLICATION_STARTING
+                    || win.mDestroying) {
+                continue;
+            }
+            if (WindowManagerService.DEBUG_VISIBILITY) {
+                Slog.v(WindowManagerService.TAG, "Win " + win + ": isDrawn="
+                        + win.isDrawnLw()
+                        + ", isAnimating=" + win.isAnimating());
+                if (!win.isDrawnLw()) {
+                    Slog.v(WindowManagerService.TAG, "Not displayed: s=" + win.mSurface
+                            + " pv=" + win.mPolicyVisibility
+                            + " dp=" + win.mDrawPending
+                            + " cdp=" + win.mCommitDrawPending
+                            + " ah=" + win.mAttachedHidden
+                            + " th="
+                            + (win.mAppToken != null
+                                    ? win.mAppToken.hiddenRequested : false)
+                            + " a=" + win.mAnimating);
+                }
+            }
+            numInteresting++;
+            if (win.isDrawnLw()) {
+                if (!win.isAnimating()) {
+                    numVisible++;
+                }
+                nowGone = false;
+            } else if (win.isAnimating()) {
+                nowGone = false;
+            }
+        }
+
+        boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting;
+        if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "VIS " + this + ": interesting="
+                + numInteresting + " visible=" + numVisible);
+        if (nowVisible != reportedVisible) {
+            if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(
+                    WindowManagerService.TAG, "Visibility changed in " + this
+                    + ": vis=" + nowVisible);
+            reportedVisible = nowVisible;
+            Message m = service.mH.obtainMessage(
+                    H.REPORT_APPLICATION_TOKEN_WINDOWS,
+                    nowVisible ? 1 : 0,
+                    nowGone ? 1 : 0,
+                    this);
+            service.mH.sendMessage(m);
+        }
+    }
+
+    WindowState findMainWindow() {
+        int j = windows.size();
+        while (j > 0) {
+            j--;
+            WindowState win = windows.get(j);
+            if (win.mAttrs.type == WindowManager.LayoutParams.TYPE_BASE_APPLICATION
+                    || win.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
+                return win;
+            }
+        }
+        return null;
+    }
+
+    void dump(PrintWriter pw, String prefix) {
+        super.dump(pw, prefix);
+        if (appToken != null) {
+            pw.print(prefix); pw.println("app=true");
+        }
+        if (allAppWindows.size() > 0) {
+            pw.print(prefix); pw.print("allAppWindows="); pw.println(allAppWindows);
+        }
+        pw.print(prefix); pw.print("groupId="); pw.print(groupId);
+                pw.print(" appFullscreen="); pw.print(appFullscreen);
+                pw.print(" requestedOrientation="); pw.println(requestedOrientation);
+        pw.print(prefix); pw.print("hiddenRequested="); pw.print(hiddenRequested);
+                pw.print(" clientHidden="); pw.print(clientHidden);
+                pw.print(" willBeHidden="); pw.print(willBeHidden);
+                pw.print(" reportedVisible="); pw.println(reportedVisible);
+        if (paused || freezingScreen) {
+            pw.print(prefix); pw.print("paused="); pw.print(paused);
+                    pw.print(" freezingScreen="); pw.println(freezingScreen);
+        }
+        if (numInterestingWindows != 0 || numDrawnWindows != 0
+                || inPendingTransaction || allDrawn) {
+            pw.print(prefix); pw.print("numInterestingWindows=");
+                    pw.print(numInterestingWindows);
+                    pw.print(" numDrawnWindows="); pw.print(numDrawnWindows);
+                    pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
+                    pw.print(" allDrawn="); pw.println(allDrawn);
+        }
+        if (animating || animation != null) {
+            pw.print(prefix); pw.print("animating="); pw.print(animating);
+                    pw.print(" animation="); pw.println(animation);
+        }
+        if (hasTransformation) {
+            pw.print(prefix); pw.print("XForm: ");
+                    transformation.printShortString(pw);
+                    pw.println();
+        }
+        if (animLayerAdjustment != 0) {
+            pw.print(prefix); pw.print("animLayerAdjustment="); pw.println(animLayerAdjustment);
+        }
+        if (startingData != null || removed || firstWindowDrawn) {
+            pw.print(prefix); pw.print("startingData="); pw.print(startingData);
+                    pw.print(" removed="); pw.print(removed);
+                    pw.print(" firstWindowDrawn="); pw.println(firstWindowDrawn);
+        }
+        if (startingWindow != null || startingView != null
+                || startingDisplayed || startingMoved) {
+            pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
+                    pw.print(" startingView="); pw.print(startingView);
+                    pw.print(" startingDisplayed="); pw.print(startingDisplayed);
+                    pw.print(" startingMoved"); pw.println(startingMoved);
+        }
+    }
+
+    @Override
+    public String toString() {
+        if (stringName == null) {
+            StringBuilder sb = new StringBuilder();
+            sb.append("AppWindowToken{");
+            sb.append(Integer.toHexString(System.identityHashCode(this)));
+            sb.append(" token="); sb.append(token); sb.append('}');
+            stringName = sb.toString();
+        }
+        return stringName;
+    }
+}
\ No newline at end of file
diff --git a/services/java/com/android/server/wm/DimAnimator.java b/services/java/com/android/server/wm/DimAnimator.java
new file mode 100644
index 0000000..1fcb869
--- /dev/null
+++ b/services/java/com/android/server/wm/DimAnimator.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import android.content.res.Resources;
+import android.graphics.PixelFormat;
+import android.util.Slog;
+import android.util.TypedValue;
+import android.view.Surface;
+import android.view.SurfaceSession;
+
+import java.io.PrintWriter;
+
+/**
+ * DimAnimator class that controls the dim animation. This holds the surface and
+ * all state used for dim animation.
+ */
+class DimAnimator {
+    Surface mDimSurface;
+    boolean mDimShown = false;
+    float mDimCurrentAlpha;
+    float mDimTargetAlpha;
+    float mDimDeltaPerMs;
+    long mLastDimAnimTime;
+    
+    int mLastDimWidth, mLastDimHeight;
+
+    DimAnimator (SurfaceSession session) {
+        if (mDimSurface == null) {
+            if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "  DIM "
+                    + mDimSurface + ": CREATE");
+            try {
+                mDimSurface = new Surface(session, 0,
+                        "DimSurface",
+                        -1, 16, 16, PixelFormat.OPAQUE,
+                        Surface.FX_SURFACE_DIM);
+                mDimSurface.setAlpha(0.0f);
+            } catch (Exception e) {
+                Slog.e(WindowManagerService.TAG, "Exception creating Dim surface", e);
+            }
+        }
+    }
+
+    /**
+     * Show the dim surface.
+     */
+    void show(int dw, int dh) {
+        if (!mDimShown) {
+            if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "  DIM " + mDimSurface + ": SHOW pos=(0,0) (" +
+                    dw + "x" + dh + ")");
+            mDimShown = true;
+            try {
+                mLastDimWidth = dw;
+                mLastDimHeight = dh;
+                mDimSurface.setPosition(0, 0);
+                mDimSurface.setSize(dw, dh);
+                mDimSurface.show();
+            } catch (RuntimeException e) {
+                Slog.w(WindowManagerService.TAG, "Failure showing dim surface", e);
+            }
+        } else if (mLastDimWidth != dw || mLastDimHeight != dh) {
+            mLastDimWidth = dw;
+            mLastDimHeight = dh;
+            mDimSurface.setSize(dw, dh);
+        }
+    }
+
+    /**
+     * Set's the dim surface's layer and update dim parameters that will be used in
+     * {@link updateSurface} after all windows are examined.
+     */
+    void updateParameters(Resources res, WindowState w, long currentTime) {
+        mDimSurface.setLayer(w.mAnimLayer-1);
+
+        final float target = w.mExiting ? 0 : w.mAttrs.dimAmount;
+        if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "  DIM " + mDimSurface
+                + ": layer=" + (w.mAnimLayer-1) + " target=" + target);
+        if (mDimTargetAlpha != target) {
+            // If the desired dim level has changed, then
+            // start an animation to it.
+            mLastDimAnimTime = currentTime;
+            long duration = (w.mAnimating && w.mAnimation != null)
+                    ? w.mAnimation.computeDurationHint()
+                    : WindowManagerService.DEFAULT_DIM_DURATION;
+            if (target > mDimTargetAlpha) {
+                TypedValue tv = new TypedValue();
+                res.getValue(com.android.internal.R.fraction.config_dimBehindFadeDuration,
+                        tv, true);
+                if (tv.type == TypedValue.TYPE_FRACTION) {
+                    duration = (long)tv.getFraction((float)duration, (float)duration);
+                } else if (tv.type >= TypedValue.TYPE_FIRST_INT
+                        && tv.type <= TypedValue.TYPE_LAST_INT) {
+                    duration = tv.data;
+                }
+            }
+            if (duration < 1) {
+                // Don't divide by zero
+                duration = 1;
+            }
+            mDimTargetAlpha = target;
+            mDimDeltaPerMs = (mDimTargetAlpha-mDimCurrentAlpha) / duration;
+        }
+    }
+
+    /**
+     * Updating the surface's alpha. Returns true if the animation continues, or returns
+     * false when the animation is finished and the dim surface is hidden.
+     */
+    boolean updateSurface(boolean dimming, long currentTime, boolean displayFrozen) {
+        if (!dimming) {
+            if (mDimTargetAlpha != 0) {
+                mLastDimAnimTime = currentTime;
+                mDimTargetAlpha = 0;
+                mDimDeltaPerMs = (-mDimCurrentAlpha) / WindowManagerService.DEFAULT_DIM_DURATION;
+            }
+        }
+
+        boolean animating = false;
+        if (mLastDimAnimTime != 0) {
+            mDimCurrentAlpha += mDimDeltaPerMs
+                    * (currentTime-mLastDimAnimTime);
+            boolean more = true;
+            if (displayFrozen) {
+                // If the display is frozen, there is no reason to animate.
+                more = false;
+            } else if (mDimDeltaPerMs > 0) {
+                if (mDimCurrentAlpha > mDimTargetAlpha) {
+                    more = false;
+                }
+            } else if (mDimDeltaPerMs < 0) {
+                if (mDimCurrentAlpha < mDimTargetAlpha) {
+                    more = false;
+                }
+            } else {
+                more = false;
+            }
+
+            // Do we need to continue animating?
+            if (more) {
+                if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "  DIM "
+                        + mDimSurface + ": alpha=" + mDimCurrentAlpha);
+                mLastDimAnimTime = currentTime;
+                mDimSurface.setAlpha(mDimCurrentAlpha);
+                animating = true;
+            } else {
+                mDimCurrentAlpha = mDimTargetAlpha;
+                mLastDimAnimTime = 0;
+                if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "  DIM "
+                        + mDimSurface + ": final alpha=" + mDimCurrentAlpha);
+                mDimSurface.setAlpha(mDimCurrentAlpha);
+                if (!dimming) {
+                    if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "  DIM " + mDimSurface
+                            + ": HIDE");
+                    try {
+                        mDimSurface.hide();
+                    } catch (RuntimeException e) {
+                        Slog.w(WindowManagerService.TAG, "Illegal argument exception hiding dim surface");
+                    }
+                    mDimShown = false;
+                }
+            }
+        }
+        return animating;
+    }
+
+    public void printTo(PrintWriter pw) {
+        pw.print("  mDimShown="); pw.print(mDimShown);
+        pw.print(" current="); pw.print(mDimCurrentAlpha);
+        pw.print(" target="); pw.print(mDimTargetAlpha);
+        pw.print(" delta="); pw.print(mDimDeltaPerMs);
+        pw.print(" lastAnimTime="); pw.println(mLastDimAnimTime);
+    }
+}
\ No newline at end of file
diff --git a/services/java/com/android/server/wm/DragState.java b/services/java/com/android/server/wm/DragState.java
new file mode 100644
index 0000000..c8f8ff3
--- /dev/null
+++ b/services/java/com/android/server/wm/DragState.java
@@ -0,0 +1,368 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import com.android.server.wm.WindowManagerService.H;
+
+import android.content.ClipData;
+import android.content.ClipDescription;
+import android.graphics.Region;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Process;
+import android.os.RemoteException;
+import android.util.Slog;
+import android.view.DragEvent;
+import android.view.InputChannel;
+import android.view.InputQueue;
+import android.view.Surface;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.WindowManagerPolicy;
+
+import java.util.ArrayList;
+
+/**
+ * Drag/drop state
+ */
+class DragState {
+    final WindowManagerService mService;
+    IBinder mToken;
+    Surface mSurface;
+    int mFlags;
+    IBinder mLocalWin;
+    ClipData mData;
+    ClipDescription mDataDescription;
+    boolean mDragResult;
+    float mCurrentX, mCurrentY;
+    float mThumbOffsetX, mThumbOffsetY;
+    InputChannel mServerChannel, mClientChannel;
+    WindowState mTargetWindow;
+    ArrayList<WindowState> mNotifiedWindows;
+    boolean mDragInProgress;
+
+    private final Region mTmpRegion = new Region();
+
+    DragState(WindowManagerService service, IBinder token, Surface surface,
+            int flags, IBinder localWin) {
+        mService = service;
+        mToken = token;
+        mSurface = surface;
+        mFlags = flags;
+        mLocalWin = localWin;
+        mNotifiedWindows = new ArrayList<WindowState>();
+    }
+
+    void reset() {
+        if (mSurface != null) {
+            mSurface.destroy();
+        }
+        mSurface = null;
+        mFlags = 0;
+        mLocalWin = null;
+        mToken = null;
+        mData = null;
+        mThumbOffsetX = mThumbOffsetY = 0;
+        mNotifiedWindows = null;
+    }
+
+    void register() {
+        if (WindowManagerService.DEBUG_DRAG) Slog.d(WindowManagerService.TAG, "registering drag input channel");
+        if (mClientChannel != null) {
+            Slog.e(WindowManagerService.TAG, "Duplicate register of drag input channel");
+        } else {
+            InputChannel[] channels = InputChannel.openInputChannelPair("drag");
+            mServerChannel = channels[0];
+            mClientChannel = channels[1];
+            mService.mInputManager.registerInputChannel(mServerChannel, null);
+            InputQueue.registerInputChannel(mClientChannel, mService.mDragInputHandler,
+                    mService.mH.getLooper().getQueue());
+        }
+    }
+
+    void unregister() {
+        if (WindowManagerService.DEBUG_DRAG) Slog.d(WindowManagerService.TAG, "unregistering drag input channel");
+        if (mClientChannel == null) {
+            Slog.e(WindowManagerService.TAG, "Unregister of nonexistent drag input channel");
+        } else {
+            mService.mInputManager.unregisterInputChannel(mServerChannel);
+            InputQueue.unregisterInputChannel(mClientChannel);
+            mClientChannel.dispose();
+            mServerChannel.dispose();
+            mClientChannel = null;
+            mServerChannel = null;
+        }
+    }
+
+    int getDragLayerLw() {
+        return mService.mPolicy.windowTypeToLayerLw(WindowManager.LayoutParams.TYPE_DRAG)
+                * WindowManagerService.TYPE_LAYER_MULTIPLIER
+                + WindowManagerService.TYPE_LAYER_OFFSET;
+    }
+
+    /* call out to each visible window/session informing it about the drag
+     */
+    void broadcastDragStartedLw(final float touchX, final float touchY) {
+        // Cache a base-class instance of the clip metadata so that parceling
+        // works correctly in calling out to the apps.
+        mDataDescription = (mData != null) ? mData.getDescription() : null;
+        mNotifiedWindows.clear();
+        mDragInProgress = true;
+
+        if (WindowManagerService.DEBUG_DRAG) {
+            Slog.d(WindowManagerService.TAG, "broadcasting DRAG_STARTED at (" + touchX + ", " + touchY + ")");
+        }
+
+        final int N = mService.mWindows.size();
+        for (int i = 0; i < N; i++) {
+            sendDragStartedLw(mService.mWindows.get(i), touchX, touchY, mDataDescription);
+        }
+    }
+
+    /* helper - send a caller-provided event, presumed to be DRAG_STARTED, if the
+     * designated window is potentially a drop recipient.  There are race situations
+     * around DRAG_ENDED broadcast, so we make sure that once we've declared that
+     * the drag has ended, we never send out another DRAG_STARTED for this drag action.
+     *
+     * This method clones the 'event' parameter if it's being delivered to the same
+     * process, so it's safe for the caller to call recycle() on the event afterwards.
+     */
+    private void sendDragStartedLw(WindowState newWin, float touchX, float touchY,
+            ClipDescription desc) {
+        // Don't actually send the event if the drag is supposed to be pinned
+        // to the originating window but 'newWin' is not that window.
+        if ((mFlags & View.DRAG_FLAG_GLOBAL) == 0) {
+            final IBinder winBinder = newWin.mClient.asBinder();
+            if (winBinder != mLocalWin) {
+                if (WindowManagerService.DEBUG_DRAG) {
+                    Slog.d(WindowManagerService.TAG, "Not dispatching local DRAG_STARTED to " + newWin);
+                }
+                return;
+            }
+        }
+
+        if (mDragInProgress && newWin.isPotentialDragTarget()) {
+            DragEvent event = DragEvent.obtain(DragEvent.ACTION_DRAG_STARTED,
+                    touchX - newWin.mFrame.left, touchY - newWin.mFrame.top,
+                    null, desc, null, false);
+            try {
+                newWin.mClient.dispatchDragEvent(event);
+                // track each window that we've notified that the drag is starting
+                mNotifiedWindows.add(newWin);
+            } catch (RemoteException e) {
+                Slog.w(WindowManagerService.TAG, "Unable to drag-start window " + newWin);
+            } finally {
+                // if the callee was local, the dispatch has already recycled the event
+                if (Process.myPid() != newWin.mSession.mPid) {
+                    event.recycle();
+                }
+            }
+        }
+    }
+
+    /* helper - construct and send a DRAG_STARTED event only if the window has not
+     * previously been notified, i.e. it became visible after the drag operation
+     * was begun.  This is a rare case.
+     */
+    void sendDragStartedIfNeededLw(WindowState newWin) {
+        if (mDragInProgress) {
+            // If we have sent the drag-started, we needn't do so again
+            for (WindowState ws : mNotifiedWindows) {
+                if (ws == newWin) {
+                    return;
+                }
+            }
+            if (WindowManagerService.DEBUG_DRAG) {
+                Slog.d(WindowManagerService.TAG, "need to send DRAG_STARTED to new window " + newWin);
+            }
+            sendDragStartedLw(newWin, mCurrentX, mCurrentY, mDataDescription);
+        }
+    }
+
+    void broadcastDragEndedLw() {
+        if (WindowManagerService.DEBUG_DRAG) {
+            Slog.d(WindowManagerService.TAG, "broadcasting DRAG_ENDED");
+        }
+        DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_ENDED,
+                0, 0, null, null, null, mDragResult);
+        for (WindowState ws: mNotifiedWindows) {
+            try {
+                ws.mClient.dispatchDragEvent(evt);
+            } catch (RemoteException e) {
+                Slog.w(WindowManagerService.TAG, "Unable to drag-end window " + ws);
+            }
+        }
+        mNotifiedWindows.clear();
+        mDragInProgress = false;
+        evt.recycle();
+    }
+
+    void endDragLw() {
+        mService.mDragState.broadcastDragEndedLw();
+
+        // stop intercepting input
+        mService.mDragState.unregister();
+        mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
+
+        // free our resources and drop all the object references
+        mService.mDragState.reset();
+        mService.mDragState = null;
+
+        if (WindowManagerService.DEBUG_ORIENTATION) Slog.d(WindowManagerService.TAG, "Performing post-drag rotation");
+        boolean changed = mService.setRotationUncheckedLocked(
+                WindowManagerPolicy.USE_LAST_ROTATION, 0, false);
+        if (changed) {
+            mService.mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
+        }
+    }
+
+    void notifyMoveLw(float x, float y) {
+        final int myPid = Process.myPid();
+
+        // Move the surface to the given touch
+        if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, ">>> OPEN TRANSACTION notifyMoveLw");
+        Surface.openTransaction();
+        try {
+            mSurface.setPosition((int)(x - mThumbOffsetX), (int)(y - mThumbOffsetY));
+            if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "  DRAG "
+                    + mSurface + ": pos=(" +
+                    (int)(x - mThumbOffsetX) + "," + (int)(y - mThumbOffsetY) + ")");
+        } finally {
+            Surface.closeTransaction();
+            if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "<<< CLOSE TRANSACTION notifyMoveLw");
+        }
+
+        // Tell the affected window
+        WindowState touchedWin = getTouchedWinAtPointLw(x, y);
+        if (touchedWin == null) {
+            if (WindowManagerService.DEBUG_DRAG) Slog.d(WindowManagerService.TAG, "No touched win at x=" + x + " y=" + y);
+            return;
+        }
+        if ((mFlags & View.DRAG_FLAG_GLOBAL) == 0) {
+            final IBinder touchedBinder = touchedWin.mClient.asBinder();
+            if (touchedBinder != mLocalWin) {
+                // This drag is pinned only to the originating window, but the drag
+                // point is outside that window.  Pretend it's over empty space.
+                touchedWin = null;
+            }
+        }
+        try {
+            // have we dragged over a new window?
+            if ((touchedWin != mTargetWindow) && (mTargetWindow != null)) {
+                if (WindowManagerService.DEBUG_DRAG) {
+                    Slog.d(WindowManagerService.TAG, "sending DRAG_EXITED to " + mTargetWindow);
+                }
+                // force DRAG_EXITED_EVENT if appropriate
+                DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_EXITED,
+                        x - mTargetWindow.mFrame.left, y - mTargetWindow.mFrame.top,
+                        null, null, null, false);
+                mTargetWindow.mClient.dispatchDragEvent(evt);
+                if (myPid != mTargetWindow.mSession.mPid) {
+                    evt.recycle();
+                }
+            }
+            if (touchedWin != null) {
+                if (false && WindowManagerService.DEBUG_DRAG) {
+                    Slog.d(WindowManagerService.TAG, "sending DRAG_LOCATION to " + touchedWin);
+                }
+                DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_LOCATION,
+                        x - touchedWin.mFrame.left, y - touchedWin.mFrame.top,
+                        null, null, null, false);
+                touchedWin.mClient.dispatchDragEvent(evt);
+                if (myPid != touchedWin.mSession.mPid) {
+                    evt.recycle();
+                }
+            }
+        } catch (RemoteException e) {
+            Slog.w(WindowManagerService.TAG, "can't send drag notification to windows");
+        }
+        mTargetWindow = touchedWin;
+    }
+
+    // Tell the drop target about the data.  Returns 'true' if we can immediately
+    // dispatch the global drag-ended message, 'false' if we need to wait for a
+    // result from the recipient.
+    boolean notifyDropLw(float x, float y) {
+        WindowState touchedWin = getTouchedWinAtPointLw(x, y);
+        if (touchedWin == null) {
+            // "drop" outside a valid window -- no recipient to apply a
+            // timeout to, and we can send the drag-ended message immediately.
+            mDragResult = false;
+            return true;
+        }
+
+        if (WindowManagerService.DEBUG_DRAG) {
+            Slog.d(WindowManagerService.TAG, "sending DROP to " + touchedWin);
+        }
+        final int myPid = Process.myPid();
+        final IBinder token = touchedWin.mClient.asBinder();
+        DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DROP,
+                x - touchedWin.mFrame.left, y - touchedWin.mFrame.top,
+                null, null, mData, false);
+        try {
+            touchedWin.mClient.dispatchDragEvent(evt);
+
+            // 5 second timeout for this window to respond to the drop
+            mService.mH.removeMessages(H.DRAG_END_TIMEOUT, token);
+            Message msg = mService.mH.obtainMessage(H.DRAG_END_TIMEOUT, token);
+            mService.mH.sendMessageDelayed(msg, 5000);
+        } catch (RemoteException e) {
+            Slog.w(WindowManagerService.TAG, "can't send drop notification to win " + touchedWin);
+            return true;
+        } finally {
+            if (myPid != touchedWin.mSession.mPid) {
+                evt.recycle();
+            }
+        }
+        mToken = token;
+        return false;
+    }
+
+    // Find the visible, touch-deliverable window under the given point
+    private WindowState getTouchedWinAtPointLw(float xf, float yf) {
+        WindowState touchedWin = null;
+        final int x = (int) xf;
+        final int y = (int) yf;
+        final ArrayList<WindowState> windows = mService.mWindows;
+        final int N = windows.size();
+        for (int i = N - 1; i >= 0; i--) {
+            WindowState child = windows.get(i);
+            final int flags = child.mAttrs.flags;
+            if (!child.isVisibleLw()) {
+                // not visible == don't tell about drags
+                continue;
+            }
+            if ((flags & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0) {
+                // not touchable == don't tell about drags
+                continue;
+            }
+
+            child.getTouchableRegion(mTmpRegion);
+
+            final int touchFlags = flags &
+                    (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                            | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
+            if (mTmpRegion.contains(x, y) || touchFlags == 0) {
+                // Found it
+                touchedWin = child;
+                break;
+            }
+        }
+
+        return touchedWin;
+    }
+}
\ No newline at end of file
diff --git a/services/java/com/android/server/wm/FadeInOutAnimation.java b/services/java/com/android/server/wm/FadeInOutAnimation.java
new file mode 100644
index 0000000..06f7657
--- /dev/null
+++ b/services/java/com/android/server/wm/FadeInOutAnimation.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.Animation;
+import android.view.animation.Transformation;
+
+/**
+ * Animation that fade in after 0.5 interpolate time, or fade out in reverse order.
+ * This is used for opening/closing transition for apps in compatible mode.
+ */
+class FadeInOutAnimation extends Animation {
+    boolean mFadeIn;
+
+    public FadeInOutAnimation(boolean fadeIn) {
+        setInterpolator(new AccelerateInterpolator());
+        setDuration(WindowManagerService.DEFAULT_FADE_IN_OUT_DURATION);
+        mFadeIn = fadeIn;
+    }
+
+    @Override
+    protected void applyTransformation(float interpolatedTime, Transformation t) {
+        float x = interpolatedTime;
+        if (!mFadeIn) {
+            x = 1.0f - x; // reverse the interpolation for fade out
+        }
+        t.setAlpha(x);
+    }
+}
\ No newline at end of file
diff --git a/services/java/com/android/server/wm/InputApplicationHandle.java b/services/java/com/android/server/wm/InputApplicationHandle.java
index c95e525..64c8e7e 100644
--- a/services/java/com/android/server/wm/InputApplicationHandle.java
+++ b/services/java/com/android/server/wm/InputApplicationHandle.java
@@ -30,11 +30,11 @@
     private int ptr;
 
     // The window manager's application window token.
-    public final WindowManagerService.AppWindowToken appWindowToken;
+    public final AppWindowToken appWindowToken;
 
     private native void nativeDispose();
 
-    public InputApplicationHandle(WindowManagerService.AppWindowToken appWindowToken) {
+    public InputApplicationHandle(AppWindowToken appWindowToken) {
         this.appWindowToken = appWindowToken;
     }
 
diff --git a/services/java/com/android/server/wm/InputMonitor.java b/services/java/com/android/server/wm/InputMonitor.java
new file mode 100644
index 0000000..34f3618
--- /dev/null
+++ b/services/java/com/android/server/wm/InputMonitor.java
@@ -0,0 +1,364 @@
+/**
+ * 
+ */
+package com.android.server.wm;
+
+import android.graphics.Rect;
+import android.os.Process;
+import android.os.RemoteException;
+import android.util.Log;
+import android.util.Slog;
+import android.view.KeyEvent;
+import android.view.WindowManager;
+
+import java.util.ArrayList;
+
+final class InputMonitor {
+    private final WindowManagerService mService;
+    
+    // Current window with input focus for keys and other non-touch events.  May be null.
+    private WindowState mInputFocus;
+    
+    // When true, prevents input dispatch from proceeding until set to false again.
+    private boolean mInputDispatchFrozen;
+    
+    // When true, input dispatch proceeds normally.  Otherwise all events are dropped.
+    private boolean mInputDispatchEnabled = true;
+
+    // When true, need to call updateInputWindowsLw().
+    private boolean mUpdateInputWindowsNeeded = true;
+
+    // Temporary list of windows information to provide to the input dispatcher.
+    private InputWindowList mTempInputWindows = new InputWindowList();
+    
+    // Temporary input application object to provide to the input dispatcher.
+    private InputApplication mTempInputApplication = new InputApplication();
+    
+    // Set to true when the first input device configuration change notification
+    // is received to indicate that the input devices are ready.
+    private final Object mInputDevicesReadyMonitor = new Object();
+    private boolean mInputDevicesReady;
+
+    public InputMonitor(WindowManagerService service) {
+        mService = service;
+    }
+    
+    /* Notifies the window manager about a broken input channel.
+     * 
+     * Called by the InputManager.
+     */
+    public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) {
+        if (inputWindowHandle == null) {
+            return;
+        }
+
+        synchronized (mService.mWindowMap) {
+            WindowState windowState = (WindowState) inputWindowHandle.windowState;
+            Slog.i(WindowManagerService.TAG, "WINDOW DIED " + windowState);
+            mService.removeWindowLocked(windowState.mSession, windowState);
+        }
+    }
+    
+    /* Notifies the window manager about an application that is not responding.
+     * Returns a new timeout to continue waiting in nanoseconds, or 0 to abort dispatch.
+     * 
+     * Called by the InputManager.
+     */
+    public long notifyANR(InputApplicationHandle inputApplicationHandle,
+            InputWindowHandle inputWindowHandle) {
+        AppWindowToken appWindowToken = null;
+        if (inputWindowHandle != null) {
+            synchronized (mService.mWindowMap) {
+                WindowState windowState = (WindowState) inputWindowHandle.windowState;
+                if (windowState != null) {
+                    Slog.i(WindowManagerService.TAG, "Input event dispatching timed out sending to "
+                            + windowState.mAttrs.getTitle());
+                    appWindowToken = windowState.mAppToken;
+                }
+            }
+        }
+        
+        if (appWindowToken == null && inputApplicationHandle != null) {
+            appWindowToken = inputApplicationHandle.appWindowToken;
+            Slog.i(WindowManagerService.TAG, "Input event dispatching timed out sending to application "
+                    + appWindowToken.stringName);
+        }
+
+        if (appWindowToken != null && appWindowToken.appToken != null) {
+            try {
+                // Notify the activity manager about the timeout and let it decide whether
+                // to abort dispatching or keep waiting.
+                boolean abort = appWindowToken.appToken.keyDispatchingTimedOut();
+                if (! abort) {
+                    // The activity manager declined to abort dispatching.
+                    // Wait a bit longer and timeout again later.
+                    return appWindowToken.inputDispatchingTimeoutNanos;
+                }
+            } catch (RemoteException ex) {
+            }
+        }
+        return 0; // abort dispatching
+    }
+
+    private void addDragInputWindowLw(InputWindowList windowList) {
+        final InputWindow inputWindow = windowList.add();
+        inputWindow.inputChannel = mService.mDragState.mServerChannel;
+        inputWindow.name = "drag";
+        inputWindow.layoutParamsFlags = 0;
+        inputWindow.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG;
+        inputWindow.dispatchingTimeoutNanos = WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
+        inputWindow.visible = true;
+        inputWindow.canReceiveKeys = false;
+        inputWindow.hasFocus = true;
+        inputWindow.hasWallpaper = false;
+        inputWindow.paused = false;
+        inputWindow.layer = mService.mDragState.getDragLayerLw();
+        inputWindow.ownerPid = Process.myPid();
+        inputWindow.ownerUid = Process.myUid();
+
+        // The drag window covers the entire display
+        inputWindow.frameLeft = 0;
+        inputWindow.frameTop = 0;
+        inputWindow.frameRight = mService.mDisplay.getWidth();
+        inputWindow.frameBottom = mService.mDisplay.getHeight();
+
+        // The drag window cannot receive new touches.
+        inputWindow.touchableRegion.setEmpty();
+    }
+
+    public void setUpdateInputWindowsNeededLw() {
+        mUpdateInputWindowsNeeded = true;
+    }
+
+    /* Updates the cached window information provided to the input dispatcher. */
+    public void updateInputWindowsLw(boolean force) {
+        if (!force && !mUpdateInputWindowsNeeded) {
+            return;
+        }
+        mUpdateInputWindowsNeeded = false;
+
+        // Populate the input window list with information about all of the windows that
+        // could potentially receive input.
+        // As an optimization, we could try to prune the list of windows but this turns
+        // out to be difficult because only the native code knows for sure which window
+        // currently has touch focus.
+        final ArrayList<WindowState> windows = mService.mWindows;
+
+        // If there's a drag in flight, provide a pseudowindow to catch drag input
+        final boolean inDrag = (mService.mDragState != null);
+        if (inDrag) {
+            if (WindowManagerService.DEBUG_DRAG) {
+                Log.d(WindowManagerService.TAG, "Inserting drag window");
+            }
+            addDragInputWindowLw(mTempInputWindows);
+        }
+
+        final int N = windows.size();
+        for (int i = N - 1; i >= 0; i--) {
+            final WindowState child = windows.get(i);
+            if (child.mInputChannel == null || child.mRemoved) {
+                // Skip this window because it cannot possibly receive input.
+                continue;
+            }
+            
+            final int flags = child.mAttrs.flags;
+            final int type = child.mAttrs.type;
+            
+            final boolean hasFocus = (child == mInputFocus);
+            final boolean isVisible = child.isVisibleLw();
+            final boolean hasWallpaper = (child == mService.mWallpaperTarget)
+                    && (type != WindowManager.LayoutParams.TYPE_KEYGUARD);
+
+            // If there's a drag in progress and 'child' is a potential drop target,
+            // make sure it's been told about the drag
+            if (inDrag && isVisible) {
+                mService.mDragState.sendDragStartedIfNeededLw(child);
+            }
+
+            // Add a window to our list of input windows.
+            final InputWindow inputWindow = mTempInputWindows.add();
+            inputWindow.inputWindowHandle = child.mInputWindowHandle;
+            inputWindow.inputChannel = child.mInputChannel;
+            inputWindow.name = child.toString();
+            inputWindow.layoutParamsFlags = flags;
+            inputWindow.layoutParamsType = type;
+            inputWindow.dispatchingTimeoutNanos = child.getInputDispatchingTimeoutNanos();
+            inputWindow.visible = isVisible;
+            inputWindow.canReceiveKeys = child.canReceiveKeys();
+            inputWindow.hasFocus = hasFocus;
+            inputWindow.hasWallpaper = hasWallpaper;
+            inputWindow.paused = child.mAppToken != null ? child.mAppToken.paused : false;
+            inputWindow.layer = child.mLayer;
+            inputWindow.ownerPid = child.mSession.mPid;
+            inputWindow.ownerUid = child.mSession.mUid;
+            
+            final Rect frame = child.mFrame;
+            inputWindow.frameLeft = frame.left;
+            inputWindow.frameTop = frame.top;
+            inputWindow.frameRight = frame.right;
+            inputWindow.frameBottom = frame.bottom;
+
+            child.getTouchableRegion(inputWindow.touchableRegion);
+        }
+
+        // Send windows to native code.
+        mService.mInputManager.setInputWindows(mTempInputWindows.toNullTerminatedArray());
+        
+        // Clear the list in preparation for the next round.
+        // Also avoids keeping InputChannel objects referenced unnecessarily.
+        mTempInputWindows.clear();
+    }
+
+    /* Notifies that the input device configuration has changed. */
+    public void notifyConfigurationChanged() {
+        mService.sendNewConfiguration();
+
+        synchronized (mInputDevicesReadyMonitor) {
+            if (!mInputDevicesReady) {
+                mInputDevicesReady = true;
+                mInputDevicesReadyMonitor.notifyAll();
+            }
+        }
+    }
+
+    /* Waits until the built-in input devices have been configured. */
+    public boolean waitForInputDevicesReady(long timeoutMillis) {
+        synchronized (mInputDevicesReadyMonitor) {
+            if (!mInputDevicesReady) {
+                try {
+                    mInputDevicesReadyMonitor.wait(timeoutMillis);
+                } catch (InterruptedException ex) {
+                }
+            }
+            return mInputDevicesReady;
+        }
+    }
+
+    /* Notifies that the lid switch changed state. */
+    public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
+        mService.mPolicy.notifyLidSwitchChanged(whenNanos, lidOpen);
+    }
+    
+    /* Provides an opportunity for the window manager policy to intercept early key
+     * processing as soon as the key has been read from the device. */
+    public int interceptKeyBeforeQueueing(
+            KeyEvent event, int policyFlags, boolean isScreenOn) {
+        return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags, isScreenOn);
+    }
+    
+    /* Provides an opportunity for the window manager policy to process a key before
+     * ordinary dispatch. */
+    public boolean interceptKeyBeforeDispatching(
+            InputWindowHandle focus, KeyEvent event, int policyFlags) {
+        WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
+        return mService.mPolicy.interceptKeyBeforeDispatching(windowState, event, policyFlags);
+    }
+    
+    /* Provides an opportunity for the window manager policy to process a key that
+     * the application did not handle. */
+    public KeyEvent dispatchUnhandledKey(
+            InputWindowHandle focus, KeyEvent event, int policyFlags) {
+        WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
+        return mService.mPolicy.dispatchUnhandledKey(windowState, event, policyFlags);
+    }
+    
+    /* Called when the current input focus changes.
+     * Layer assignment is assumed to be complete by the time this is called.
+     */
+    public void setInputFocusLw(WindowState newWindow, boolean updateInputWindows) {
+        if (WindowManagerService.DEBUG_INPUT) {
+            Slog.d(WindowManagerService.TAG, "Input focus has changed to " + newWindow);
+        }
+
+        if (newWindow != mInputFocus) {
+            if (newWindow != null && newWindow.canReceiveKeys()) {
+                // Displaying a window implicitly causes dispatching to be unpaused.
+                // This is to protect against bugs if someone pauses dispatching but
+                // forgets to resume.
+                newWindow.mToken.paused = false;
+            }
+
+            mInputFocus = newWindow;
+            setUpdateInputWindowsNeededLw();
+
+            if (updateInputWindows) {
+                updateInputWindowsLw(false /*force*/);
+            }
+        }
+    }
+    
+    public void setFocusedAppLw(AppWindowToken newApp) {
+        // Focused app has changed.
+        if (newApp == null) {
+            mService.mInputManager.setFocusedApplication(null);
+        } else {
+            mTempInputApplication.inputApplicationHandle = newApp.mInputApplicationHandle;
+            mTempInputApplication.name = newApp.toString();
+            mTempInputApplication.dispatchingTimeoutNanos =
+                    newApp.inputDispatchingTimeoutNanos;
+
+            mService.mInputManager.setFocusedApplication(mTempInputApplication);
+
+            mTempInputApplication.recycle();
+        }
+    }
+    
+    public void pauseDispatchingLw(WindowToken window) {
+        if (! window.paused) {
+            if (WindowManagerService.DEBUG_INPUT) {
+                Slog.v(WindowManagerService.TAG, "Pausing WindowToken " + window);
+            }
+            
+            window.paused = true;
+            updateInputWindowsLw(true /*force*/);
+        }
+    }
+    
+    public void resumeDispatchingLw(WindowToken window) {
+        if (window.paused) {
+            if (WindowManagerService.DEBUG_INPUT) {
+                Slog.v(WindowManagerService.TAG, "Resuming WindowToken " + window);
+            }
+            
+            window.paused = false;
+            updateInputWindowsLw(true /*force*/);
+        }
+    }
+    
+    public void freezeInputDispatchingLw() {
+        if (! mInputDispatchFrozen) {
+            if (WindowManagerService.DEBUG_INPUT) {
+                Slog.v(WindowManagerService.TAG, "Freezing input dispatching");
+            }
+            
+            mInputDispatchFrozen = true;
+            updateInputDispatchModeLw();
+        }
+    }
+    
+    public void thawInputDispatchingLw() {
+        if (mInputDispatchFrozen) {
+            if (WindowManagerService.DEBUG_INPUT) {
+                Slog.v(WindowManagerService.TAG, "Thawing input dispatching");
+            }
+            
+            mInputDispatchFrozen = false;
+            updateInputDispatchModeLw();
+        }
+    }
+    
+    public void setEventDispatchingLw(boolean enabled) {
+        if (mInputDispatchEnabled != enabled) {
+            if (WindowManagerService.DEBUG_INPUT) {
+                Slog.v(WindowManagerService.TAG, "Setting event dispatching to " + enabled);
+            }
+            
+            mInputDispatchEnabled = enabled;
+            updateInputDispatchModeLw();
+        }
+    }
+    
+    private void updateInputDispatchModeLw() {
+        mService.mInputManager.setInputDispatchMode(mInputDispatchEnabled, mInputDispatchFrozen);
+    }
+}
\ No newline at end of file
diff --git a/services/java/com/android/server/wm/ScreenRotationAnimation.java b/services/java/com/android/server/wm/ScreenRotationAnimation.java
index fc9f10e..4356ce5 100644
--- a/services/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.wm;  // TODO: use com.android.server.wm, once things move there
-
+package com.android.server.wm;
 
 import android.content.Context;
 import android.graphics.Bitmap;
diff --git a/services/java/com/android/server/wm/Session.java b/services/java/com/android/server/wm/Session.java
new file mode 100644
index 0000000..b9db177
--- /dev/null
+++ b/services/java/com/android/server/wm/Session.java
@@ -0,0 +1,419 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import com.android.internal.view.IInputContext;
+import com.android.internal.view.IInputMethodClient;
+import com.android.internal.view.IInputMethodManager;
+import com.android.server.wm.WindowManagerService.H;
+
+import android.content.ClipData;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Slog;
+import android.view.IWindow;
+import android.view.IWindowSession;
+import android.view.InputChannel;
+import android.view.Surface;
+import android.view.SurfaceSession;
+import android.view.WindowManager;
+
+import java.io.PrintWriter;
+
+/**
+ * This class represents an active client session.  There is generally one
+ * Session object per process that is interacting with the window manager.
+ */
+final class Session extends IWindowSession.Stub
+        implements IBinder.DeathRecipient {
+    final WindowManagerService mService;
+    final IInputMethodClient mClient;
+    final IInputContext mInputContext;
+    final int mUid;
+    final int mPid;
+    final String mStringName;
+    SurfaceSession mSurfaceSession;
+    int mNumWindow = 0;
+    boolean mClientDead = false;
+
+    public Session(WindowManagerService service, IInputMethodClient client,
+            IInputContext inputContext) {
+        mService = service;
+        mClient = client;
+        mInputContext = inputContext;
+        mUid = Binder.getCallingUid();
+        mPid = Binder.getCallingPid();
+        StringBuilder sb = new StringBuilder();
+        sb.append("Session{");
+        sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(" uid ");
+        sb.append(mUid);
+        sb.append("}");
+        mStringName = sb.toString();
+
+        synchronized (mService.mWindowMap) {
+            if (mService.mInputMethodManager == null && mService.mHaveInputMethods) {
+                IBinder b = ServiceManager.getService(
+                        Context.INPUT_METHOD_SERVICE);
+                mService.mInputMethodManager = IInputMethodManager.Stub.asInterface(b);
+            }
+        }
+        long ident = Binder.clearCallingIdentity();
+        try {
+            // Note: it is safe to call in to the input method manager
+            // here because we are not holding our lock.
+            if (mService.mInputMethodManager != null) {
+                mService.mInputMethodManager.addClient(client, inputContext,
+                        mUid, mPid);
+            } else {
+                client.setUsingInputMethod(false);
+            }
+            client.asBinder().linkToDeath(this, 0);
+        } catch (RemoteException e) {
+            // The caller has died, so we can just forget about this.
+            try {
+                if (mService.mInputMethodManager != null) {
+                    mService.mInputMethodManager.removeClient(client);
+                }
+            } catch (RemoteException ee) {
+            }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    @Override
+    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
+            throws RemoteException {
+        try {
+            return super.onTransact(code, data, reply, flags);
+        } catch (RuntimeException e) {
+            // Log all 'real' exceptions thrown to the caller
+            if (!(e instanceof SecurityException)) {
+                Slog.e(WindowManagerService.TAG, "Window Session Crash", e);
+            }
+            throw e;
+        }
+    }
+
+    public void binderDied() {
+        // Note: it is safe to call in to the input method manager
+        // here because we are not holding our lock.
+        try {
+            if (mService.mInputMethodManager != null) {
+                mService.mInputMethodManager.removeClient(mClient);
+            }
+        } catch (RemoteException e) {
+        }
+        synchronized(mService.mWindowMap) {
+            mClient.asBinder().unlinkToDeath(this, 0);
+            mClientDead = true;
+            killSessionLocked();
+        }
+    }
+
+    public int add(IWindow window, WindowManager.LayoutParams attrs,
+            int viewVisibility, Rect outContentInsets, InputChannel outInputChannel) {
+        return mService.addWindow(this, window, attrs, viewVisibility, outContentInsets,
+                outInputChannel);
+    }
+    
+    public int addWithoutInputChannel(IWindow window, WindowManager.LayoutParams attrs,
+            int viewVisibility, Rect outContentInsets) {
+        return mService.addWindow(this, window, attrs, viewVisibility, outContentInsets, null);
+    }
+
+    public void remove(IWindow window) {
+        mService.removeWindow(this, window);
+    }
+
+    public int relayout(IWindow window, WindowManager.LayoutParams attrs,
+            int requestedWidth, int requestedHeight, int viewFlags,
+            boolean insetsPending, Rect outFrame, Rect outContentInsets,
+            Rect outVisibleInsets, Configuration outConfig, Surface outSurface) {
+        //Log.d(TAG, ">>>>>> ENTERED relayout from " + Binder.getCallingPid());
+        int res = mService.relayoutWindow(this, window, attrs,
+                requestedWidth, requestedHeight, viewFlags, insetsPending,
+                outFrame, outContentInsets, outVisibleInsets, outConfig, outSurface);
+        //Log.d(TAG, "<<<<<< EXITING relayout to " + Binder.getCallingPid());
+        return res;
+    }
+
+    public void setTransparentRegion(IWindow window, Region region) {
+        mService.setTransparentRegionWindow(this, window, region);
+    }
+
+    public void setInsets(IWindow window, int touchableInsets,
+            Rect contentInsets, Rect visibleInsets, Region touchableArea) {
+        mService.setInsetsWindow(this, window, touchableInsets, contentInsets,
+                visibleInsets, touchableArea);
+    }
+
+    public void getDisplayFrame(IWindow window, Rect outDisplayFrame) {
+        mService.getWindowDisplayFrame(this, window, outDisplayFrame);
+    }
+
+    public void finishDrawing(IWindow window) {
+        if (WindowManagerService.localLOGV) Slog.v(
+            WindowManagerService.TAG, "IWindow finishDrawing called for " + window);
+        mService.finishDrawingWindow(this, window);
+    }
+
+    public void setInTouchMode(boolean mode) {
+        synchronized(mService.mWindowMap) {
+            mService.mInTouchMode = mode;
+        }
+    }
+
+    public boolean getInTouchMode() {
+        synchronized(mService.mWindowMap) {
+            return mService.mInTouchMode;
+        }
+    }
+
+    public boolean performHapticFeedback(IWindow window, int effectId,
+            boolean always) {
+        synchronized(mService.mWindowMap) {
+            long ident = Binder.clearCallingIdentity();
+            try {
+                return mService.mPolicy.performHapticFeedbackLw(
+                        mService.windowForClientLocked(this, window, true),
+                        effectId, always);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+    }
+
+    /* Drag/drop */
+    public IBinder prepareDrag(IWindow window, int flags,
+            int width, int height, Surface outSurface) {
+        return mService.prepareDragSurface(window, mSurfaceSession, flags,
+                width, height, outSurface);
+    }
+
+    public boolean performDrag(IWindow window, IBinder dragToken,
+            float touchX, float touchY, float thumbCenterX, float thumbCenterY,
+            ClipData data) {
+        if (WindowManagerService.DEBUG_DRAG) {
+            Slog.d(WindowManagerService.TAG, "perform drag: win=" + window + " data=" + data);
+        }
+
+        synchronized (mService.mWindowMap) {
+            if (mService.mDragState == null) {
+                Slog.w(WindowManagerService.TAG, "No drag prepared");
+                throw new IllegalStateException("performDrag() without prepareDrag()");
+            }
+
+            if (dragToken != mService.mDragState.mToken) {
+                Slog.w(WindowManagerService.TAG, "Performing mismatched drag");
+                throw new IllegalStateException("performDrag() does not match prepareDrag()");
+            }
+
+            WindowState callingWin = mService.windowForClientLocked(null, window, false);
+            if (callingWin == null) {
+                Slog.w(WindowManagerService.TAG, "Bad requesting window " + window);
+                return false;  // !!! TODO: throw here?
+            }
+
+            // !!! TODO: if input is not still focused on the initiating window, fail
+            // the drag initiation (e.g. an alarm window popped up just as the application
+            // called performDrag()
+
+            mService.mH.removeMessages(H.DRAG_START_TIMEOUT, window.asBinder());
+
+            // !!! TODO: extract the current touch (x, y) in screen coordinates.  That
+            // will let us eliminate the (touchX,touchY) parameters from the API.
+
+            // !!! FIXME: put all this heavy stuff onto the mH looper, as well as
+            // the actual drag event dispatch stuff in the dragstate
+
+            mService.mDragState.register();
+            mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
+            if (!mService.mInputManager.transferTouchFocus(callingWin.mInputChannel,
+                    mService.mDragState.mServerChannel)) {
+                Slog.e(WindowManagerService.TAG, "Unable to transfer touch focus");
+                mService.mDragState.unregister();
+                mService.mDragState = null;
+                mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
+                return false;
+            }
+
+            mService.mDragState.mData = data;
+            mService.mDragState.mCurrentX = touchX;
+            mService.mDragState.mCurrentY = touchY;
+            mService.mDragState.broadcastDragStartedLw(touchX, touchY);
+
+            // remember the thumb offsets for later
+            mService.mDragState.mThumbOffsetX = thumbCenterX;
+            mService.mDragState.mThumbOffsetY = thumbCenterY;
+
+            // Make the surface visible at the proper location
+            final Surface surface = mService.mDragState.mSurface;
+            if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, ">>> OPEN TRANSACTION performDrag");
+            Surface.openTransaction();
+            try {
+                surface.setPosition((int)(touchX - thumbCenterX),
+                        (int)(touchY - thumbCenterY));
+                surface.setAlpha(.7071f);
+                surface.setLayer(mService.mDragState.getDragLayerLw());
+                surface.show();
+            } finally {
+                Surface.closeTransaction();
+                if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "<<< CLOSE TRANSACTION performDrag");
+            }
+        }
+
+        return true;    // success!
+    }
+
+    public void reportDropResult(IWindow window, boolean consumed) {
+        IBinder token = window.asBinder();
+        if (WindowManagerService.DEBUG_DRAG) {
+            Slog.d(WindowManagerService.TAG, "Drop result=" + consumed + " reported by " + token);
+        }
+
+        synchronized (mService.mWindowMap) {
+            long ident = Binder.clearCallingIdentity();
+            try {
+                if (mService.mDragState == null || mService.mDragState.mToken != token) {
+                    Slog.w(WindowManagerService.TAG, "Invalid drop-result claim by " + window);
+                    throw new IllegalStateException("reportDropResult() by non-recipient");
+                }
+
+                // The right window has responded, even if it's no longer around,
+                // so be sure to halt the timeout even if the later WindowState
+                // lookup fails.
+                mService.mH.removeMessages(H.DRAG_END_TIMEOUT, window.asBinder());
+                WindowState callingWin = mService.windowForClientLocked(null, window, false);
+                if (callingWin == null) {
+                    Slog.w(WindowManagerService.TAG, "Bad result-reporting window " + window);
+                    return;  // !!! TODO: throw here?
+                }
+
+                mService.mDragState.mDragResult = consumed;
+                mService.mDragState.endDragLw();
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+    }
+
+    public void dragRecipientEntered(IWindow window) {
+        if (WindowManagerService.DEBUG_DRAG) {
+            Slog.d(WindowManagerService.TAG, "Drag into new candidate view @ " + window.asBinder());
+        }
+    }
+
+    public void dragRecipientExited(IWindow window) {
+        if (WindowManagerService.DEBUG_DRAG) {
+            Slog.d(WindowManagerService.TAG, "Drag from old candidate view @ " + window.asBinder());
+        }
+    }
+
+    public void setWallpaperPosition(IBinder window, float x, float y, float xStep, float yStep) {
+        synchronized(mService.mWindowMap) {
+            long ident = Binder.clearCallingIdentity();
+            try {
+                mService.setWindowWallpaperPositionLocked(
+                        mService.windowForClientLocked(this, window, true),
+                        x, y, xStep, yStep);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+    }
+
+    public void wallpaperOffsetsComplete(IBinder window) {
+        mService.wallpaperOffsetsComplete(window);
+    }
+
+    public Bundle sendWallpaperCommand(IBinder window, String action, int x, int y,
+            int z, Bundle extras, boolean sync) {
+        synchronized(mService.mWindowMap) {
+            long ident = Binder.clearCallingIdentity();
+            try {
+                return mService.sendWindowWallpaperCommandLocked(
+                        mService.windowForClientLocked(this, window, true),
+                        action, x, y, z, extras, sync);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+    }
+
+    public void wallpaperCommandComplete(IBinder window, Bundle result) {
+        mService.wallpaperCommandComplete(window, result);
+    }
+
+    void windowAddedLocked() {
+        if (mSurfaceSession == null) {
+            if (WindowManagerService.localLOGV) Slog.v(
+                WindowManagerService.TAG, "First window added to " + this + ", creating SurfaceSession");
+            mSurfaceSession = new SurfaceSession();
+            if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
+                    WindowManagerService.TAG, "  NEW SURFACE SESSION " + mSurfaceSession);
+            mService.mSessions.add(this);
+        }
+        mNumWindow++;
+    }
+
+    void windowRemovedLocked() {
+        mNumWindow--;
+        killSessionLocked();
+    }
+
+    void killSessionLocked() {
+        if (mNumWindow <= 0 && mClientDead) {
+            mService.mSessions.remove(this);
+            if (mSurfaceSession != null) {
+                if (WindowManagerService.localLOGV) Slog.v(
+                    WindowManagerService.TAG, "Last window removed from " + this
+                    + ", destroying " + mSurfaceSession);
+                if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
+                        WindowManagerService.TAG, "  KILL SURFACE SESSION " + mSurfaceSession);
+                try {
+                    mSurfaceSession.kill();
+                } catch (Exception e) {
+                    Slog.w(WindowManagerService.TAG, "Exception thrown when killing surface session "
+                        + mSurfaceSession + " in session " + this
+                        + ": " + e.toString());
+                }
+                mSurfaceSession = null;
+            }
+        }
+    }
+
+    void dump(PrintWriter pw, String prefix) {
+        pw.print(prefix); pw.print("mNumWindow="); pw.print(mNumWindow);
+                pw.print(" mClientDead="); pw.print(mClientDead);
+                pw.print(" mSurfaceSession="); pw.println(mSurfaceSession);
+    }
+
+    @Override
+    public String toString() {
+        return mStringName;
+    }
+}
\ No newline at end of file
diff --git a/services/java/com/android/server/wm/StartingData.java b/services/java/com/android/server/wm/StartingData.java
new file mode 100644
index 0000000..625fcfe
--- /dev/null
+++ b/services/java/com/android/server/wm/StartingData.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+final class StartingData {
+    final String pkg;
+    final int theme;
+    final CharSequence nonLocalizedLabel;
+    final int labelRes;
+    final int icon;
+    final int windowFlags;
+
+    StartingData(String _pkg, int _theme, CharSequence _nonLocalizedLabel,
+            int _labelRes, int _icon, int _windowFlags) {
+        pkg = _pkg;
+        theme = _theme;
+        nonLocalizedLabel = _nonLocalizedLabel;
+        labelRes = _labelRes;
+        icon = _icon;
+        windowFlags = _windowFlags;
+    }
+}
\ No newline at end of file
diff --git a/services/java/com/android/server/wm/StrictModeFlash.java b/services/java/com/android/server/wm/StrictModeFlash.java
index 2aa45ac..2c62080 100644
--- a/services/java/com/android/server/wm/StrictModeFlash.java
+++ b/services/java/com/android/server/wm/StrictModeFlash.java
@@ -14,13 +14,12 @@
  * limitations under the License.
  */
 
-package com.android.server.wm;  // TODO: use com.android.server.wm, once things move there
+package com.android.server.wm;
 
 
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.PixelFormat;
-import android.graphics.PorterDuff;
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.util.DisplayMetrics;
diff --git a/services/java/com/android/server/wm/Watermark.java b/services/java/com/android/server/wm/Watermark.java
new file mode 100644
index 0000000..22126f3
--- /dev/null
+++ b/services/java/com/android/server/wm/Watermark.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.Rect;
+import android.graphics.Typeface;
+import android.graphics.Paint.FontMetricsInt;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.Display;
+import android.view.Surface;
+import android.view.SurfaceSession;
+import android.view.Surface.OutOfResourcesException;
+
+/**
+ * Displays a watermark on top of the window manager's windows.
+ */
+class Watermark {
+    final String[] mTokens;
+    final String mText;
+    final Paint mTextPaint;
+    final int mTextWidth;
+    final int mTextHeight;
+    final int mTextAscent;
+    final int mTextDescent;
+    final int mDeltaX;
+    final int mDeltaY;
+
+    Surface mSurface;
+    int mLastDW;
+    int mLastDH;
+    boolean mDrawNeeded;
+
+    Watermark(Display display, SurfaceSession session, String[] tokens) {
+        final DisplayMetrics dm = new DisplayMetrics();
+        display.getMetrics(dm);
+
+        if (false) {
+            Log.i(WindowManagerService.TAG, "*********************** WATERMARK");
+            for (int i=0; i<tokens.length; i++) {
+                Log.i(WindowManagerService.TAG, "  TOKEN #" + i + ": " + tokens[i]);
+            }
+        }
+
+        mTokens = tokens;
+
+        StringBuilder builder = new StringBuilder(32);
+        int len = mTokens[0].length();
+        len = len & ~1;
+        for (int i=0; i<len; i+=2) {
+            int c1 = mTokens[0].charAt(i);
+            int c2 = mTokens[0].charAt(i+1);
+            if (c1 >= 'a' && c1 <= 'f') c1 = c1 - 'a' + 10;
+            else if (c1 >= 'A' && c1 <= 'F') c1 = c1 - 'A' + 10;
+            else c1 -= '0';
+            if (c2 >= 'a' && c2 <= 'f') c2 = c2 - 'a' + 10;
+            else if (c2 >= 'A' && c2 <= 'F') c2 = c2 - 'A' + 10;
+            else c2 -= '0';
+            builder.append((char)(255-((c1*16)+c2)));
+        }
+        mText = builder.toString();
+        if (false) {
+            Log.i(WindowManagerService.TAG, "Final text: " + mText);
+        }
+
+        int fontSize = WindowManagerService.getPropertyInt(tokens, 1,
+                TypedValue.COMPLEX_UNIT_DIP, 20, dm);
+
+        mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        mTextPaint.setTextSize(fontSize);
+        mTextPaint.setTypeface(Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD));
+
+        FontMetricsInt fm = mTextPaint.getFontMetricsInt();
+        mTextWidth = (int)mTextPaint.measureText(mText);
+        mTextAscent = fm.ascent;
+        mTextDescent = fm.descent;
+        mTextHeight = fm.descent - fm.ascent;
+
+        mDeltaX = WindowManagerService.getPropertyInt(tokens, 2,
+                TypedValue.COMPLEX_UNIT_PX, mTextWidth*2, dm);
+        mDeltaY = WindowManagerService.getPropertyInt(tokens, 3,
+                TypedValue.COMPLEX_UNIT_PX, mTextHeight*3, dm);
+        int shadowColor = WindowManagerService.getPropertyInt(tokens, 4,
+                TypedValue.COMPLEX_UNIT_PX, 0xb0000000, dm);
+        int color = WindowManagerService.getPropertyInt(tokens, 5,
+                TypedValue.COMPLEX_UNIT_PX, 0x60ffffff, dm);
+        int shadowRadius = WindowManagerService.getPropertyInt(tokens, 6,
+                TypedValue.COMPLEX_UNIT_PX, 7, dm);
+        int shadowDx = WindowManagerService.getPropertyInt(tokens, 8,
+                TypedValue.COMPLEX_UNIT_PX, 0, dm);
+        int shadowDy = WindowManagerService.getPropertyInt(tokens, 9,
+                TypedValue.COMPLEX_UNIT_PX, 0, dm);
+
+        mTextPaint.setColor(color);
+        mTextPaint.setShadowLayer(shadowRadius, shadowDx, shadowDy, shadowColor);
+
+        try {
+            mSurface = new Surface(session, 0,
+                    "WatermarkSurface", -1, 1, 1, PixelFormat.TRANSLUCENT, 0);
+            mSurface.setLayer(WindowManagerService.TYPE_LAYER_MULTIPLIER*100);
+            mSurface.setPosition(0, 0);
+            mSurface.show();
+        } catch (OutOfResourcesException e) {
+        }
+    }
+
+    void positionSurface(int dw, int dh) {
+        if (mLastDW != dw || mLastDH != dh) {
+            mLastDW = dw;
+            mLastDH = dh;
+            mSurface.setSize(dw, dh);
+            mDrawNeeded = true;
+        }
+    }
+
+    void drawIfNeeded() {
+        if (mDrawNeeded) {
+            final int dw = mLastDW;
+            final int dh = mLastDH;
+
+            mDrawNeeded = false;
+            Rect dirty = new Rect(0, 0, dw, dh);
+            Canvas c = null;
+            try {
+                c = mSurface.lockCanvas(dirty);
+            } catch (IllegalArgumentException e) {
+            } catch (OutOfResourcesException e) {
+            }
+            if (c != null) {
+                c.drawColor(0, PorterDuff.Mode.CLEAR);
+                
+                int deltaX = mDeltaX;
+                int deltaY = mDeltaY;
+
+                // deltaX shouldn't be close to a round fraction of our
+                // x step, or else things will line up too much.
+                int div = (dw+mTextWidth)/deltaX;
+                int rem = (dw+mTextWidth) - (div*deltaX);
+                int qdelta = deltaX/4;
+                if (rem < qdelta || rem > (deltaX-qdelta)) {
+                    deltaX += deltaX/3;
+                }
+
+                int y = -mTextHeight;
+                int x = -mTextWidth;
+                while (y < (dh+mTextHeight)) {
+                    c.drawText(mText, x, y, mTextPaint);
+                    x += deltaX;
+                    if (x >= dw) {
+                        x -= (dw+mTextWidth);
+                        y += deltaY;
+                    }
+                }
+                mSurface.unlockCanvasAndPost(c);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 3183643..a598ce9 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -22,7 +22,6 @@
 import static android.view.WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
 import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
 import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
-import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
 import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
@@ -46,8 +45,6 @@
 import com.android.server.EventLogTags;
 import com.android.server.PowerManagerService;
 import com.android.server.Watchdog;
-import com.android.server.AttributeCache.Entry;
-import com.android.server.Watchdog.Monitor;
 import com.android.server.am.BatteryStatsService;
 
 import android.Manifest;
@@ -56,8 +53,6 @@
 import android.app.StatusBarManager;
 import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
-import android.content.ClipData;
-import android.content.ClipDescription;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -65,17 +60,12 @@
 import android.content.pm.PackageManager;
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
-import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Matrix;
-import android.graphics.Paint;
 import android.graphics.PixelFormat;
-import android.graphics.PorterDuff;
 import android.graphics.Rect;
 import android.graphics.Region;
-import android.graphics.Typeface;
-import android.graphics.Paint.FontMetricsInt;
 import android.os.BatteryStats;
 import android.os.Binder;
 import android.os.Bundle;
@@ -104,8 +94,6 @@
 import android.util.SparseIntArray;
 import android.util.TypedValue;
 import android.view.Display;
-import android.view.DragEvent;
-import android.view.Gravity;
 import android.view.IApplicationToken;
 import android.view.IOnKeyguardExitResult;
 import android.view.IRotationWatcher;
@@ -122,13 +110,10 @@
 import android.view.Surface;
 import android.view.SurfaceSession;
 import android.view.View;
-import android.view.ViewTreeObserver;
 import android.view.WindowManager;
 import android.view.WindowManagerImpl;
 import android.view.WindowManagerPolicy;
-import android.view.Surface.OutOfResourcesException;
 import android.view.WindowManager.LayoutParams;
-import android.view.animation.AccelerateInterpolator;
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
 import android.view.animation.Transformation;
@@ -225,7 +210,7 @@
     private static final int INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS = 1000;
     
     // Default input dispatching timeout in nanoseconds.
-    private static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L;
+    static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L;
 
     static final int UPDATE_FOCUS_NORMAL = 0;
     static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1;
@@ -513,336 +498,8 @@
 
     boolean mTurnOnScreen;
 
-    /**
-     * Drag/drop state
-     */
-    class DragState {
-        IBinder mToken;
-        Surface mSurface;
-        int mFlags;
-        IBinder mLocalWin;
-        ClipData mData;
-        ClipDescription mDataDescription;
-        boolean mDragResult;
-        float mCurrentX, mCurrentY;
-        float mThumbOffsetX, mThumbOffsetY;
-        InputChannel mServerChannel, mClientChannel;
-        WindowState mTargetWindow;
-        ArrayList<WindowState> mNotifiedWindows;
-        boolean mDragInProgress;
-
-        private final Region mTmpRegion = new Region();
-
-        DragState(IBinder token, Surface surface, int flags, IBinder localWin) {
-            mToken = token;
-            mSurface = surface;
-            mFlags = flags;
-            mLocalWin = localWin;
-            mNotifiedWindows = new ArrayList<WindowState>();
-        }
-
-        void reset() {
-            if (mSurface != null) {
-                mSurface.destroy();
-            }
-            mSurface = null;
-            mFlags = 0;
-            mLocalWin = null;
-            mToken = null;
-            mData = null;
-            mThumbOffsetX = mThumbOffsetY = 0;
-            mNotifiedWindows = null;
-        }
-
-        void register() {
-            if (DEBUG_DRAG) Slog.d(TAG, "registering drag input channel");
-            if (mClientChannel != null) {
-                Slog.e(TAG, "Duplicate register of drag input channel");
-            } else {
-                InputChannel[] channels = InputChannel.openInputChannelPair("drag");
-                mServerChannel = channels[0];
-                mClientChannel = channels[1];
-                mInputManager.registerInputChannel(mServerChannel, null);
-                InputQueue.registerInputChannel(mClientChannel, mDragInputHandler,
-                        mH.getLooper().getQueue());
-            }
-        }
-
-        void unregister() {
-            if (DEBUG_DRAG) Slog.d(TAG, "unregistering drag input channel");
-            if (mClientChannel == null) {
-                Slog.e(TAG, "Unregister of nonexistent drag input channel");
-            } else {
-                mInputManager.unregisterInputChannel(mServerChannel);
-                InputQueue.unregisterInputChannel(mClientChannel);
-                mClientChannel.dispose();
-                mServerChannel.dispose();
-                mClientChannel = null;
-                mServerChannel = null;
-            }
-        }
-
-        int getDragLayerLw() {
-            return mPolicy.windowTypeToLayerLw(WindowManager.LayoutParams.TYPE_DRAG)
-                    * TYPE_LAYER_MULTIPLIER
-                    + TYPE_LAYER_OFFSET;
-        }
-
-        /* call out to each visible window/session informing it about the drag
-         */
-        void broadcastDragStartedLw(final float touchX, final float touchY) {
-            // Cache a base-class instance of the clip metadata so that parceling
-            // works correctly in calling out to the apps.
-            mDataDescription = (mData != null) ? mData.getDescription() : null;
-            mNotifiedWindows.clear();
-            mDragInProgress = true;
-
-            if (DEBUG_DRAG) {
-                Slog.d(TAG, "broadcasting DRAG_STARTED at (" + touchX + ", " + touchY + ")");
-            }
-
-            final int N = mWindows.size();
-            for (int i = 0; i < N; i++) {
-                sendDragStartedLw(mWindows.get(i), touchX, touchY, mDataDescription);
-            }
-        }
-
-        /* helper - send a caller-provided event, presumed to be DRAG_STARTED, if the
-         * designated window is potentially a drop recipient.  There are race situations
-         * around DRAG_ENDED broadcast, so we make sure that once we've declared that
-         * the drag has ended, we never send out another DRAG_STARTED for this drag action.
-         *
-         * This method clones the 'event' parameter if it's being delivered to the same
-         * process, so it's safe for the caller to call recycle() on the event afterwards.
-         */
-        private void sendDragStartedLw(WindowState newWin, float touchX, float touchY,
-                ClipDescription desc) {
-            // Don't actually send the event if the drag is supposed to be pinned
-            // to the originating window but 'newWin' is not that window.
-            if ((mFlags & View.DRAG_FLAG_GLOBAL) == 0) {
-                final IBinder winBinder = newWin.mClient.asBinder();
-                if (winBinder != mLocalWin) {
-                    if (DEBUG_DRAG) {
-                        Slog.d(TAG, "Not dispatching local DRAG_STARTED to " + newWin);
-                    }
-                    return;
-                }
-            }
-
-            if (mDragInProgress && newWin.isPotentialDragTarget()) {
-                DragEvent event = DragEvent.obtain(DragEvent.ACTION_DRAG_STARTED,
-                        touchX - newWin.mFrame.left, touchY - newWin.mFrame.top,
-                        null, desc, null, false);
-                try {
-                    newWin.mClient.dispatchDragEvent(event);
-                    // track each window that we've notified that the drag is starting
-                    mNotifiedWindows.add(newWin);
-                } catch (RemoteException e) {
-                    Slog.w(TAG, "Unable to drag-start window " + newWin);
-                } finally {
-                    // if the callee was local, the dispatch has already recycled the event
-                    if (Process.myPid() != newWin.mSession.mPid) {
-                        event.recycle();
-                    }
-                }
-            }
-        }
-
-        /* helper - construct and send a DRAG_STARTED event only if the window has not
-         * previously been notified, i.e. it became visible after the drag operation
-         * was begun.  This is a rare case.
-         */
-        private void sendDragStartedIfNeededLw(WindowState newWin) {
-            if (mDragInProgress) {
-                // If we have sent the drag-started, we needn't do so again
-                for (WindowState ws : mNotifiedWindows) {
-                    if (ws == newWin) {
-                        return;
-                    }
-                }
-                if (DEBUG_DRAG) {
-                    Slog.d(TAG, "need to send DRAG_STARTED to new window " + newWin);
-                }
-                sendDragStartedLw(newWin, mCurrentX, mCurrentY, mDataDescription);
-            }
-        }
-
-        void broadcastDragEndedLw() {
-            if (DEBUG_DRAG) {
-                Slog.d(TAG, "broadcasting DRAG_ENDED");
-            }
-            DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_ENDED,
-                    0, 0, null, null, null, mDragResult);
-            for (WindowState ws: mNotifiedWindows) {
-                try {
-                    ws.mClient.dispatchDragEvent(evt);
-                } catch (RemoteException e) {
-                    Slog.w(TAG, "Unable to drag-end window " + ws);
-                }
-            }
-            mNotifiedWindows.clear();
-            mDragInProgress = false;
-            evt.recycle();
-        }
-
-        void endDragLw() {
-            mDragState.broadcastDragEndedLw();
-
-            // stop intercepting input
-            mDragState.unregister();
-            mInputMonitor.updateInputWindowsLw(true /*force*/);
-
-            // free our resources and drop all the object references
-            mDragState.reset();
-            mDragState = null;
-
-            if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-drag rotation");
-            boolean changed = setRotationUncheckedLocked(
-                    WindowManagerPolicy.USE_LAST_ROTATION, 0, false);
-            if (changed) {
-                mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
-            }
-        }
-
-        void notifyMoveLw(float x, float y) {
-            final int myPid = Process.myPid();
-
-            // Move the surface to the given touch
-            if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION notifyMoveLw");
-            Surface.openTransaction();
-            try {
-                mSurface.setPosition((int)(x - mThumbOffsetX), (int)(y - mThumbOffsetY));
-                if (SHOW_TRANSACTIONS) Slog.i(TAG, "  DRAG "
-                        + mSurface + ": pos=(" +
-                        (int)(x - mThumbOffsetX) + "," + (int)(y - mThumbOffsetY) + ")");
-            } finally {
-                Surface.closeTransaction();
-                if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION notifyMoveLw");
-            }
-
-            // Tell the affected window
-            WindowState touchedWin = getTouchedWinAtPointLw(x, y);
-            if (touchedWin == null) {
-                if (DEBUG_DRAG) Slog.d(TAG, "No touched win at x=" + x + " y=" + y);
-                return;
-            }
-            if ((mFlags & View.DRAG_FLAG_GLOBAL) == 0) {
-                final IBinder touchedBinder = touchedWin.mClient.asBinder();
-                if (touchedBinder != mLocalWin) {
-                    // This drag is pinned only to the originating window, but the drag
-                    // point is outside that window.  Pretend it's over empty space.
-                    touchedWin = null;
-                }
-            }
-            try {
-                // have we dragged over a new window?
-                if ((touchedWin != mTargetWindow) && (mTargetWindow != null)) {
-                    if (DEBUG_DRAG) {
-                        Slog.d(TAG, "sending DRAG_EXITED to " + mTargetWindow);
-                    }
-                    // force DRAG_EXITED_EVENT if appropriate
-                    DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_EXITED,
-                            x - mTargetWindow.mFrame.left, y - mTargetWindow.mFrame.top,
-                            null, null, null, false);
-                    mTargetWindow.mClient.dispatchDragEvent(evt);
-                    if (myPid != mTargetWindow.mSession.mPid) {
-                        evt.recycle();
-                    }
-                }
-                if (touchedWin != null) {
-                    if (false && DEBUG_DRAG) {
-                        Slog.d(TAG, "sending DRAG_LOCATION to " + touchedWin);
-                    }
-                    DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_LOCATION,
-                            x - touchedWin.mFrame.left, y - touchedWin.mFrame.top,
-                            null, null, null, false);
-                    touchedWin.mClient.dispatchDragEvent(evt);
-                    if (myPid != touchedWin.mSession.mPid) {
-                        evt.recycle();
-                    }
-                }
-            } catch (RemoteException e) {
-                Slog.w(TAG, "can't send drag notification to windows");
-            }
-            mTargetWindow = touchedWin;
-        }
-
-        // Tell the drop target about the data.  Returns 'true' if we can immediately
-        // dispatch the global drag-ended message, 'false' if we need to wait for a
-        // result from the recipient.
-        boolean notifyDropLw(float x, float y) {
-            WindowState touchedWin = getTouchedWinAtPointLw(x, y);
-            if (touchedWin == null) {
-                // "drop" outside a valid window -- no recipient to apply a
-                // timeout to, and we can send the drag-ended message immediately.
-                mDragResult = false;
-                return true;
-            }
-
-            if (DEBUG_DRAG) {
-                Slog.d(TAG, "sending DROP to " + touchedWin);
-            }
-            final int myPid = Process.myPid();
-            final IBinder token = touchedWin.mClient.asBinder();
-            DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DROP,
-                    x - touchedWin.mFrame.left, y - touchedWin.mFrame.top,
-                    null, null, mData, false);
-            try {
-                touchedWin.mClient.dispatchDragEvent(evt);
-
-                // 5 second timeout for this window to respond to the drop
-                mH.removeMessages(H.DRAG_END_TIMEOUT, token);
-                Message msg = mH.obtainMessage(H.DRAG_END_TIMEOUT, token);
-                mH.sendMessageDelayed(msg, 5000);
-            } catch (RemoteException e) {
-                Slog.w(TAG, "can't send drop notification to win " + touchedWin);
-                return true;
-            } finally {
-                if (myPid != touchedWin.mSession.mPid) {
-                    evt.recycle();
-                }
-            }
-            mToken = token;
-            return false;
-        }
-
-        // Find the visible, touch-deliverable window under the given point
-        private WindowState getTouchedWinAtPointLw(float xf, float yf) {
-            WindowState touchedWin = null;
-            final int x = (int) xf;
-            final int y = (int) yf;
-            final ArrayList<WindowState> windows = mWindows;
-            final int N = windows.size();
-            for (int i = N - 1; i >= 0; i--) {
-                WindowState child = windows.get(i);
-                final int flags = child.mAttrs.flags;
-                if (!child.isVisibleLw()) {
-                    // not visible == don't tell about drags
-                    continue;
-                }
-                if ((flags & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0) {
-                    // not touchable == don't tell about drags
-                    continue;
-                }
-
-                child.getTouchableRegion(mTmpRegion);
-
-                final int touchFlags = flags &
-                        (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
-                                | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
-                if (mTmpRegion.contains(x, y) || touchFlags == 0) {
-                    // Found it
-                    touchedWin = child;
-                    break;
-                }
-            }
-
-            return touchedWin;
-        }
-    }
-
     DragState mDragState = null;
-    private final InputHandler mDragInputHandler = new BaseInputHandler() {
+    final InputHandler mDragInputHandler = new BaseInputHandler() {
         @Override
         public void handleMotion(MotionEvent event, InputQueue.FinishedCallback finishedCallback) {
             boolean handled = false;
@@ -2306,7 +1963,7 @@
                           + attrs.token + ".  Aborting.");
                     return WindowManagerImpl.ADD_BAD_APP_TOKEN;
                 }
-                token = new WindowToken(attrs.token, -1, false);
+                token = new WindowToken(this, attrs.token, -1, false);
                 addToken = true;
             } else if (attrs.type >= FIRST_APPLICATION_WINDOW
                     && attrs.type <= LAST_APPLICATION_WINDOW) {
@@ -2340,7 +1997,7 @@
                 }
             }
 
-            win = new WindowState(session, client, token,
+            win = new WindowState(this, session, client, token,
                     attachedWindow, attrs, viewVisibility);
             if (win.mDeathRecipient == null) {
                 // Client has apparently died, so there is no reason to
@@ -2638,7 +2295,7 @@
         mInputMonitor.updateInputWindowsLw(true /*force*/);
     }
 
-    private static void logSurface(WindowState w, String msg, RuntimeException where) {
+    static void logSurface(WindowState w, String msg, RuntimeException where) {
         String str = "  SURFACE " + Integer.toHexString(w.hashCode())
                 + ": " + msg + " / " + w.mAttrs.getTitle();
         if (where != null) {
@@ -2648,7 +2305,7 @@
         }
     }
     
-    private void setTransparentRegionWindow(Session session, IWindow client, Region region) {
+    void setTransparentRegionWindow(Session session, IWindow client, Region region) {
         long origId = Binder.clearCallingIdentity();
         try {
             synchronized (mWindowMap) {
@@ -3102,7 +2759,7 @@
         return null;
     }
 
-    private void applyEnterAnimationLocked(WindowState win) {
+    void applyEnterAnimationLocked(WindowState win) {
         int transit = WindowManagerPolicy.TRANSIT_SHOW;
         if (win.mEnterAnimationPending) {
             win.mEnterAnimationPending = false;
@@ -3112,7 +2769,7 @@
         applyAnimationLocked(win, transit, true);
     }
 
-    private boolean applyAnimationLocked(WindowState win,
+    boolean applyAnimationLocked(WindowState win,
             int transit, boolean isEntrance) {
         if (win.mLocalAnimating && win.mAnimationIsEntrance == isEntrance) {
             // If we are trying to apply an animation, but already running
@@ -3368,7 +3025,7 @@
                 Slog.w(TAG, "Attempted to add existing input method token: " + token);
                 return;
             }
-            wtoken = new WindowToken(token, type, true);
+            wtoken = new WindowToken(this, token, type, true);
             mTokenMap.put(token, wtoken);
             if (type == TYPE_WALLPAPER) {
                 mWallpaperTokens.add(wtoken);
@@ -3456,7 +3113,7 @@
                 Slog.w(TAG, "Attempted to add existing app token: " + token);
                 return;
             }
-            wtoken = new AppWindowToken(token);
+            wtoken = new AppWindowToken(this, token);
             wtoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
             wtoken.groupId = groupId;
             wtoken.appFullscreen = fullscreen;
@@ -5584,7 +5241,7 @@
                 parameters = "";
             }
 
-            final WindowManagerService.WindowState window = findWindow(hashCode);
+            final WindowState window = findWindow(hashCode);
             if (window == null) {
                 return false;
             }
@@ -5895,7 +5552,7 @@
                         outSurface.copyFrom(surface);
                         final IBinder winBinder = window.asBinder();
                         token = new Binder();
-                        mDragState = new DragState(token, surface, /*flags*/ 0, winBinder);
+                        mDragState = new DragState(this, token, surface, /*flags*/ 0, winBinder);
                         mDragState.mSurface = surface;
                         token = mDragState.mToken = new Binder();
 
@@ -5925,355 +5582,8 @@
     // Input Events and Focus Management
     // -------------------------------------------------------------
     
-    InputMonitor mInputMonitor = new InputMonitor();
+    final InputMonitor mInputMonitor = new InputMonitor(this);
     
-    /* Tracks the progress of input dispatch and ensures that input dispatch state
-     * is kept in sync with changes in window focus, visibility, registration, and
-     * other relevant Window Manager state transitions. */
-    final class InputMonitor {
-        // Current window with input focus for keys and other non-touch events.  May be null.
-        private WindowState mInputFocus;
-        
-        // When true, prevents input dispatch from proceeding until set to false again.
-        private boolean mInputDispatchFrozen;
-        
-        // When true, input dispatch proceeds normally.  Otherwise all events are dropped.
-        private boolean mInputDispatchEnabled = true;
-
-        // When true, need to call updateInputWindowsLw().
-        private boolean mUpdateInputWindowsNeeded = true;
-
-        // Temporary list of windows information to provide to the input dispatcher.
-        private InputWindowList mTempInputWindows = new InputWindowList();
-        
-        // Temporary input application object to provide to the input dispatcher.
-        private InputApplication mTempInputApplication = new InputApplication();
-        
-        // Set to true when the first input device configuration change notification
-        // is received to indicate that the input devices are ready.
-        private final Object mInputDevicesReadyMonitor = new Object();
-        private boolean mInputDevicesReady;
-
-        /* Notifies the window manager about a broken input channel.
-         * 
-         * Called by the InputManager.
-         */
-        public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) {
-            if (inputWindowHandle == null) {
-                return;
-            }
-
-            synchronized (mWindowMap) {
-                WindowState windowState = (WindowState) inputWindowHandle.windowState;
-                Slog.i(TAG, "WINDOW DIED " + windowState);
-                removeWindowLocked(windowState.mSession, windowState);
-            }
-        }
-        
-        /* Notifies the window manager about an application that is not responding.
-         * Returns a new timeout to continue waiting in nanoseconds, or 0 to abort dispatch.
-         * 
-         * Called by the InputManager.
-         */
-        public long notifyANR(InputApplicationHandle inputApplicationHandle,
-                InputWindowHandle inputWindowHandle) {
-            AppWindowToken appWindowToken = null;
-            if (inputWindowHandle != null) {
-                synchronized (mWindowMap) {
-                    WindowState windowState = (WindowState) inputWindowHandle.windowState;
-                    if (windowState != null) {
-                        Slog.i(TAG, "Input event dispatching timed out sending to "
-                                + windowState.mAttrs.getTitle());
-                        appWindowToken = windowState.mAppToken;
-                    }
-                }
-            }
-            
-            if (appWindowToken == null && inputApplicationHandle != null) {
-                appWindowToken = inputApplicationHandle.appWindowToken;
-                Slog.i(TAG, "Input event dispatching timed out sending to application "
-                        + appWindowToken.stringName);
-            }
-
-            if (appWindowToken != null && appWindowToken.appToken != null) {
-                try {
-                    // Notify the activity manager about the timeout and let it decide whether
-                    // to abort dispatching or keep waiting.
-                    boolean abort = appWindowToken.appToken.keyDispatchingTimedOut();
-                    if (! abort) {
-                        // The activity manager declined to abort dispatching.
-                        // Wait a bit longer and timeout again later.
-                        return appWindowToken.inputDispatchingTimeoutNanos;
-                    }
-                } catch (RemoteException ex) {
-                }
-            }
-            return 0; // abort dispatching
-        }
-
-        private void addDragInputWindowLw(InputWindowList windowList) {
-            final InputWindow inputWindow = windowList.add();
-            inputWindow.inputChannel = mDragState.mServerChannel;
-            inputWindow.name = "drag";
-            inputWindow.layoutParamsFlags = 0;
-            inputWindow.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG;
-            inputWindow.dispatchingTimeoutNanos = DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
-            inputWindow.visible = true;
-            inputWindow.canReceiveKeys = false;
-            inputWindow.hasFocus = true;
-            inputWindow.hasWallpaper = false;
-            inputWindow.paused = false;
-            inputWindow.layer = mDragState.getDragLayerLw();
-            inputWindow.ownerPid = Process.myPid();
-            inputWindow.ownerUid = Process.myUid();
-
-            // The drag window covers the entire display
-            inputWindow.frameLeft = 0;
-            inputWindow.frameTop = 0;
-            inputWindow.frameRight = mDisplay.getWidth();
-            inputWindow.frameBottom = mDisplay.getHeight();
-
-            // The drag window cannot receive new touches.
-            inputWindow.touchableRegion.setEmpty();
-        }
-
-        public void setUpdateInputWindowsNeededLw() {
-            mUpdateInputWindowsNeeded = true;
-        }
-
-        /* Updates the cached window information provided to the input dispatcher. */
-        public void updateInputWindowsLw(boolean force) {
-            if (!force && !mUpdateInputWindowsNeeded) {
-                return;
-            }
-            mUpdateInputWindowsNeeded = false;
-
-            // Populate the input window list with information about all of the windows that
-            // could potentially receive input.
-            // As an optimization, we could try to prune the list of windows but this turns
-            // out to be difficult because only the native code knows for sure which window
-            // currently has touch focus.
-            final ArrayList<WindowState> windows = mWindows;
-
-            // If there's a drag in flight, provide a pseudowindow to catch drag input
-            final boolean inDrag = (mDragState != null);
-            if (inDrag) {
-                if (DEBUG_DRAG) {
-                    Log.d(TAG, "Inserting drag window");
-                }
-                addDragInputWindowLw(mTempInputWindows);
-            }
-
-            final int N = windows.size();
-            for (int i = N - 1; i >= 0; i--) {
-                final WindowState child = windows.get(i);
-                if (child.mInputChannel == null || child.mRemoved) {
-                    // Skip this window because it cannot possibly receive input.
-                    continue;
-                }
-                
-                final int flags = child.mAttrs.flags;
-                final int type = child.mAttrs.type;
-                
-                final boolean hasFocus = (child == mInputFocus);
-                final boolean isVisible = child.isVisibleLw();
-                final boolean hasWallpaper = (child == mWallpaperTarget)
-                        && (type != WindowManager.LayoutParams.TYPE_KEYGUARD);
-
-                // If there's a drag in progress and 'child' is a potential drop target,
-                // make sure it's been told about the drag
-                if (inDrag && isVisible) {
-                    mDragState.sendDragStartedIfNeededLw(child);
-                }
-
-                // Add a window to our list of input windows.
-                final InputWindow inputWindow = mTempInputWindows.add();
-                inputWindow.inputWindowHandle = child.mInputWindowHandle;
-                inputWindow.inputChannel = child.mInputChannel;
-                inputWindow.name = child.toString();
-                inputWindow.layoutParamsFlags = flags;
-                inputWindow.layoutParamsType = type;
-                inputWindow.dispatchingTimeoutNanos = child.getInputDispatchingTimeoutNanos();
-                inputWindow.visible = isVisible;
-                inputWindow.canReceiveKeys = child.canReceiveKeys();
-                inputWindow.hasFocus = hasFocus;
-                inputWindow.hasWallpaper = hasWallpaper;
-                inputWindow.paused = child.mAppToken != null ? child.mAppToken.paused : false;
-                inputWindow.layer = child.mLayer;
-                inputWindow.ownerPid = child.mSession.mPid;
-                inputWindow.ownerUid = child.mSession.mUid;
-                
-                final Rect frame = child.mFrame;
-                inputWindow.frameLeft = frame.left;
-                inputWindow.frameTop = frame.top;
-                inputWindow.frameRight = frame.right;
-                inputWindow.frameBottom = frame.bottom;
-
-                child.getTouchableRegion(inputWindow.touchableRegion);
-            }
-
-            // Send windows to native code.
-            mInputManager.setInputWindows(mTempInputWindows.toNullTerminatedArray());
-            
-            // Clear the list in preparation for the next round.
-            // Also avoids keeping InputChannel objects referenced unnecessarily.
-            mTempInputWindows.clear();
-        }
-
-        /* Notifies that the input device configuration has changed. */
-        public void notifyConfigurationChanged() {
-            sendNewConfiguration();
-
-            synchronized (mInputDevicesReadyMonitor) {
-                if (!mInputDevicesReady) {
-                    mInputDevicesReady = true;
-                    mInputDevicesReadyMonitor.notifyAll();
-                }
-            }
-        }
-
-        /* Waits until the built-in input devices have been configured. */
-        public boolean waitForInputDevicesReady(long timeoutMillis) {
-            synchronized (mInputDevicesReadyMonitor) {
-                if (!mInputDevicesReady) {
-                    try {
-                        mInputDevicesReadyMonitor.wait(timeoutMillis);
-                    } catch (InterruptedException ex) {
-                    }
-                }
-                return mInputDevicesReady;
-            }
-        }
-
-        /* Notifies that the lid switch changed state. */
-        public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
-            mPolicy.notifyLidSwitchChanged(whenNanos, lidOpen);
-        }
-        
-        /* Provides an opportunity for the window manager policy to intercept early key
-         * processing as soon as the key has been read from the device. */
-        public int interceptKeyBeforeQueueing(
-                KeyEvent event, int policyFlags, boolean isScreenOn) {
-            return mPolicy.interceptKeyBeforeQueueing(event, policyFlags, isScreenOn);
-        }
-        
-        /* Provides an opportunity for the window manager policy to process a key before
-         * ordinary dispatch. */
-        public boolean interceptKeyBeforeDispatching(
-                InputWindowHandle focus, KeyEvent event, int policyFlags) {
-            WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
-            return mPolicy.interceptKeyBeforeDispatching(windowState, event, policyFlags);
-        }
-        
-        /* Provides an opportunity for the window manager policy to process a key that
-         * the application did not handle. */
-        public KeyEvent dispatchUnhandledKey(
-                InputWindowHandle focus, KeyEvent event, int policyFlags) {
-            WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
-            return mPolicy.dispatchUnhandledKey(windowState, event, policyFlags);
-        }
-        
-        /* Called when the current input focus changes.
-         * Layer assignment is assumed to be complete by the time this is called.
-         */
-        public void setInputFocusLw(WindowState newWindow, boolean updateInputWindows) {
-            if (DEBUG_INPUT) {
-                Slog.d(TAG, "Input focus has changed to " + newWindow);
-            }
-
-            if (newWindow != mInputFocus) {
-                if (newWindow != null && newWindow.canReceiveKeys()) {
-                    // Displaying a window implicitly causes dispatching to be unpaused.
-                    // This is to protect against bugs if someone pauses dispatching but
-                    // forgets to resume.
-                    newWindow.mToken.paused = false;
-                }
-
-                mInputFocus = newWindow;
-                setUpdateInputWindowsNeededLw();
-
-                if (updateInputWindows) {
-                    updateInputWindowsLw(false /*force*/);
-                }
-            }
-        }
-        
-        public void setFocusedAppLw(AppWindowToken newApp) {
-            // Focused app has changed.
-            if (newApp == null) {
-                mInputManager.setFocusedApplication(null);
-            } else {
-                mTempInputApplication.inputApplicationHandle = newApp.mInputApplicationHandle;
-                mTempInputApplication.name = newApp.toString();
-                mTempInputApplication.dispatchingTimeoutNanos =
-                        newApp.inputDispatchingTimeoutNanos;
-
-                mInputManager.setFocusedApplication(mTempInputApplication);
-
-                mTempInputApplication.recycle();
-            }
-        }
-        
-        public void pauseDispatchingLw(WindowToken window) {
-            if (! window.paused) {
-                if (DEBUG_INPUT) {
-                    Slog.v(TAG, "Pausing WindowToken " + window);
-                }
-                
-                window.paused = true;
-                updateInputWindowsLw(true /*force*/);
-            }
-        }
-        
-        public void resumeDispatchingLw(WindowToken window) {
-            if (window.paused) {
-                if (DEBUG_INPUT) {
-                    Slog.v(TAG, "Resuming WindowToken " + window);
-                }
-                
-                window.paused = false;
-                updateInputWindowsLw(true /*force*/);
-            }
-        }
-        
-        public void freezeInputDispatchingLw() {
-            if (! mInputDispatchFrozen) {
-                if (DEBUG_INPUT) {
-                    Slog.v(TAG, "Freezing input dispatching");
-                }
-                
-                mInputDispatchFrozen = true;
-                updateInputDispatchModeLw();
-            }
-        }
-        
-        public void thawInputDispatchingLw() {
-            if (mInputDispatchFrozen) {
-                if (DEBUG_INPUT) {
-                    Slog.v(TAG, "Thawing input dispatching");
-                }
-                
-                mInputDispatchFrozen = false;
-                updateInputDispatchModeLw();
-            }
-        }
-        
-        public void setEventDispatchingLw(boolean enabled) {
-            if (mInputDispatchEnabled != enabled) {
-                if (DEBUG_INPUT) {
-                    Slog.v(TAG, "Setting event dispatching to " + enabled);
-                }
-                
-                mInputDispatchEnabled = enabled;
-                updateInputDispatchModeLw();
-            }
-        }
-        
-        private void updateInputDispatchModeLw() {
-            mInputManager.setInputDispatchMode(mInputDispatchEnabled, mInputDispatchFrozen);
-        }
-    }
-
     public void pauseKeyDispatching(IBinder _token) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "pauseKeyDispatching()")) {
@@ -6502,2409 +5812,6 @@
         mPolicy.systemReady();
     }
 
-    // -------------------------------------------------------------
-    // Client Session State
-    // -------------------------------------------------------------
-
-    private final class Session extends IWindowSession.Stub
-            implements IBinder.DeathRecipient {
-        final IInputMethodClient mClient;
-        final IInputContext mInputContext;
-        final int mUid;
-        final int mPid;
-        final String mStringName;
-        SurfaceSession mSurfaceSession;
-        int mNumWindow = 0;
-        boolean mClientDead = false;
-
-        public Session(IInputMethodClient client, IInputContext inputContext) {
-            mClient = client;
-            mInputContext = inputContext;
-            mUid = Binder.getCallingUid();
-            mPid = Binder.getCallingPid();
-            StringBuilder sb = new StringBuilder();
-            sb.append("Session{");
-            sb.append(Integer.toHexString(System.identityHashCode(this)));
-            sb.append(" uid ");
-            sb.append(mUid);
-            sb.append("}");
-            mStringName = sb.toString();
-
-            synchronized (mWindowMap) {
-                if (mInputMethodManager == null && mHaveInputMethods) {
-                    IBinder b = ServiceManager.getService(
-                            Context.INPUT_METHOD_SERVICE);
-                    mInputMethodManager = IInputMethodManager.Stub.asInterface(b);
-                }
-            }
-            long ident = Binder.clearCallingIdentity();
-            try {
-                // Note: it is safe to call in to the input method manager
-                // here because we are not holding our lock.
-                if (mInputMethodManager != null) {
-                    mInputMethodManager.addClient(client, inputContext,
-                            mUid, mPid);
-                } else {
-                    client.setUsingInputMethod(false);
-                }
-                client.asBinder().linkToDeath(this, 0);
-            } catch (RemoteException e) {
-                // The caller has died, so we can just forget about this.
-                try {
-                    if (mInputMethodManager != null) {
-                        mInputMethodManager.removeClient(client);
-                    }
-                } catch (RemoteException ee) {
-                }
-            } finally {
-                Binder.restoreCallingIdentity(ident);
-            }
-        }
-
-        @Override
-        public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
-                throws RemoteException {
-            try {
-                return super.onTransact(code, data, reply, flags);
-            } catch (RuntimeException e) {
-                // Log all 'real' exceptions thrown to the caller
-                if (!(e instanceof SecurityException)) {
-                    Slog.e(TAG, "Window Session Crash", e);
-                }
-                throw e;
-            }
-        }
-
-        public void binderDied() {
-            // Note: it is safe to call in to the input method manager
-            // here because we are not holding our lock.
-            try {
-                if (mInputMethodManager != null) {
-                    mInputMethodManager.removeClient(mClient);
-                }
-            } catch (RemoteException e) {
-            }
-            synchronized(mWindowMap) {
-                mClient.asBinder().unlinkToDeath(this, 0);
-                mClientDead = true;
-                killSessionLocked();
-            }
-        }
-
-        public int add(IWindow window, WindowManager.LayoutParams attrs,
-                int viewVisibility, Rect outContentInsets, InputChannel outInputChannel) {
-            return addWindow(this, window, attrs, viewVisibility, outContentInsets,
-                    outInputChannel);
-        }
-        
-        public int addWithoutInputChannel(IWindow window, WindowManager.LayoutParams attrs,
-                int viewVisibility, Rect outContentInsets) {
-            return addWindow(this, window, attrs, viewVisibility, outContentInsets, null);
-        }
-
-        public void remove(IWindow window) {
-            removeWindow(this, window);
-        }
-
-        public int relayout(IWindow window, WindowManager.LayoutParams attrs,
-                int requestedWidth, int requestedHeight, int viewFlags,
-                boolean insetsPending, Rect outFrame, Rect outContentInsets,
-                Rect outVisibleInsets, Configuration outConfig, Surface outSurface) {
-            //Log.d(TAG, ">>>>>> ENTERED relayout from " + Binder.getCallingPid());
-            int res = relayoutWindow(this, window, attrs,
-                    requestedWidth, requestedHeight, viewFlags, insetsPending,
-                    outFrame, outContentInsets, outVisibleInsets, outConfig, outSurface);
-            //Log.d(TAG, "<<<<<< EXITING relayout to " + Binder.getCallingPid());
-            return res;
-        }
-
-        public void setTransparentRegion(IWindow window, Region region) {
-            setTransparentRegionWindow(this, window, region);
-        }
-
-        public void setInsets(IWindow window, int touchableInsets,
-                Rect contentInsets, Rect visibleInsets, Region touchableArea) {
-            setInsetsWindow(this, window, touchableInsets, contentInsets,
-                    visibleInsets, touchableArea);
-        }
-
-        public void getDisplayFrame(IWindow window, Rect outDisplayFrame) {
-            getWindowDisplayFrame(this, window, outDisplayFrame);
-        }
-
-        public void finishDrawing(IWindow window) {
-            if (localLOGV) Slog.v(
-                TAG, "IWindow finishDrawing called for " + window);
-            finishDrawingWindow(this, window);
-        }
-
-        public void setInTouchMode(boolean mode) {
-            synchronized(mWindowMap) {
-                mInTouchMode = mode;
-            }
-        }
-
-        public boolean getInTouchMode() {
-            synchronized(mWindowMap) {
-                return mInTouchMode;
-            }
-        }
-
-        public boolean performHapticFeedback(IWindow window, int effectId,
-                boolean always) {
-            synchronized(mWindowMap) {
-                long ident = Binder.clearCallingIdentity();
-                try {
-                    return mPolicy.performHapticFeedbackLw(
-                            windowForClientLocked(this, window, true),
-                            effectId, always);
-                } finally {
-                    Binder.restoreCallingIdentity(ident);
-                }
-            }
-        }
-
-        /* Drag/drop */
-        public IBinder prepareDrag(IWindow window, int flags,
-                int width, int height, Surface outSurface) {
-            return prepareDragSurface(window, mSurfaceSession, flags,
-                    width, height, outSurface);
-        }
-
-        public boolean performDrag(IWindow window, IBinder dragToken,
-                float touchX, float touchY, float thumbCenterX, float thumbCenterY,
-                ClipData data) {
-            if (DEBUG_DRAG) {
-                Slog.d(TAG, "perform drag: win=" + window + " data=" + data);
-            }
-
-            synchronized (mWindowMap) {
-                if (mDragState == null) {
-                    Slog.w(TAG, "No drag prepared");
-                    throw new IllegalStateException("performDrag() without prepareDrag()");
-                }
-
-                if (dragToken != mDragState.mToken) {
-                    Slog.w(TAG, "Performing mismatched drag");
-                    throw new IllegalStateException("performDrag() does not match prepareDrag()");
-                }
-
-                WindowState callingWin = windowForClientLocked(null, window, false);
-                if (callingWin == null) {
-                    Slog.w(TAG, "Bad requesting window " + window);
-                    return false;  // !!! TODO: throw here?
-                }
-
-                // !!! TODO: if input is not still focused on the initiating window, fail
-                // the drag initiation (e.g. an alarm window popped up just as the application
-                // called performDrag()
-
-                mH.removeMessages(H.DRAG_START_TIMEOUT, window.asBinder());
-
-                // !!! TODO: extract the current touch (x, y) in screen coordinates.  That
-                // will let us eliminate the (touchX,touchY) parameters from the API.
-
-                // !!! FIXME: put all this heavy stuff onto the mH looper, as well as
-                // the actual drag event dispatch stuff in the dragstate
-
-                mDragState.register();
-                mInputMonitor.updateInputWindowsLw(true /*force*/);
-                if (!mInputManager.transferTouchFocus(callingWin.mInputChannel,
-                        mDragState.mServerChannel)) {
-                    Slog.e(TAG, "Unable to transfer touch focus");
-                    mDragState.unregister();
-                    mDragState = null;
-                    mInputMonitor.updateInputWindowsLw(true /*force*/);
-                    return false;
-                }
-
-                mDragState.mData = data;
-                mDragState.mCurrentX = touchX;
-                mDragState.mCurrentY = touchY;
-                mDragState.broadcastDragStartedLw(touchX, touchY);
-
-                // remember the thumb offsets for later
-                mDragState.mThumbOffsetX = thumbCenterX;
-                mDragState.mThumbOffsetY = thumbCenterY;
-
-                // Make the surface visible at the proper location
-                final Surface surface = mDragState.mSurface;
-                if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION performDrag");
-                Surface.openTransaction();
-                try {
-                    surface.setPosition((int)(touchX - thumbCenterX),
-                            (int)(touchY - thumbCenterY));
-                    surface.setAlpha(.7071f);
-                    surface.setLayer(mDragState.getDragLayerLw());
-                    surface.show();
-                } finally {
-                    Surface.closeTransaction();
-                    if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION performDrag");
-                }
-            }
-
-            return true;    // success!
-        }
-
-        public void reportDropResult(IWindow window, boolean consumed) {
-            IBinder token = window.asBinder();
-            if (DEBUG_DRAG) {
-                Slog.d(TAG, "Drop result=" + consumed + " reported by " + token);
-            }
-
-            synchronized (mWindowMap) {
-                long ident = Binder.clearCallingIdentity();
-                try {
-                    if (mDragState == null || mDragState.mToken != token) {
-                        Slog.w(TAG, "Invalid drop-result claim by " + window);
-                        throw new IllegalStateException("reportDropResult() by non-recipient");
-                    }
-
-                    // The right window has responded, even if it's no longer around,
-                    // so be sure to halt the timeout even if the later WindowState
-                    // lookup fails.
-                    mH.removeMessages(H.DRAG_END_TIMEOUT, window.asBinder());
-                    WindowState callingWin = windowForClientLocked(null, window, false);
-                    if (callingWin == null) {
-                        Slog.w(TAG, "Bad result-reporting window " + window);
-                        return;  // !!! TODO: throw here?
-                    }
-
-                    mDragState.mDragResult = consumed;
-                    mDragState.endDragLw();
-                } finally {
-                    Binder.restoreCallingIdentity(ident);
-                }
-            }
-        }
-
-        public void dragRecipientEntered(IWindow window) {
-            if (DEBUG_DRAG) {
-                Slog.d(TAG, "Drag into new candidate view @ " + window.asBinder());
-            }
-        }
-
-        public void dragRecipientExited(IWindow window) {
-            if (DEBUG_DRAG) {
-                Slog.d(TAG, "Drag from old candidate view @ " + window.asBinder());
-            }
-        }
-
-        public void setWallpaperPosition(IBinder window, float x, float y, float xStep, float yStep) {
-            synchronized(mWindowMap) {
-                long ident = Binder.clearCallingIdentity();
-                try {
-                    setWindowWallpaperPositionLocked(
-                            windowForClientLocked(this, window, true),
-                            x, y, xStep, yStep);
-                } finally {
-                    Binder.restoreCallingIdentity(ident);
-                }
-            }
-        }
-
-        public void wallpaperOffsetsComplete(IBinder window) {
-            WindowManagerService.this.wallpaperOffsetsComplete(window);
-        }
-
-        public Bundle sendWallpaperCommand(IBinder window, String action, int x, int y,
-                int z, Bundle extras, boolean sync) {
-            synchronized(mWindowMap) {
-                long ident = Binder.clearCallingIdentity();
-                try {
-                    return sendWindowWallpaperCommandLocked(
-                            windowForClientLocked(this, window, true),
-                            action, x, y, z, extras, sync);
-                } finally {
-                    Binder.restoreCallingIdentity(ident);
-                }
-            }
-        }
-
-        public void wallpaperCommandComplete(IBinder window, Bundle result) {
-            WindowManagerService.this.wallpaperCommandComplete(window, result);
-        }
-
-        void windowAddedLocked() {
-            if (mSurfaceSession == null) {
-                if (localLOGV) Slog.v(
-                    TAG, "First window added to " + this + ", creating SurfaceSession");
-                mSurfaceSession = new SurfaceSession();
-                if (SHOW_TRANSACTIONS) Slog.i(
-                        TAG, "  NEW SURFACE SESSION " + mSurfaceSession);
-                mSessions.add(this);
-            }
-            mNumWindow++;
-        }
-
-        void windowRemovedLocked() {
-            mNumWindow--;
-            killSessionLocked();
-        }
-
-        void killSessionLocked() {
-            if (mNumWindow <= 0 && mClientDead) {
-                mSessions.remove(this);
-                if (mSurfaceSession != null) {
-                    if (localLOGV) Slog.v(
-                        TAG, "Last window removed from " + this
-                        + ", destroying " + mSurfaceSession);
-                    if (SHOW_TRANSACTIONS) Slog.i(
-                            TAG, "  KILL SURFACE SESSION " + mSurfaceSession);
-                    try {
-                        mSurfaceSession.kill();
-                    } catch (Exception e) {
-                        Slog.w(TAG, "Exception thrown when killing surface session "
-                            + mSurfaceSession + " in session " + this
-                            + ": " + e.toString());
-                    }
-                    mSurfaceSession = null;
-                }
-            }
-        }
-
-        void dump(PrintWriter pw, String prefix) {
-            pw.print(prefix); pw.print("mNumWindow="); pw.print(mNumWindow);
-                    pw.print(" mClientDead="); pw.print(mClientDead);
-                    pw.print(" mSurfaceSession="); pw.println(mSurfaceSession);
-        }
-
-        @Override
-        public String toString() {
-            return mStringName;
-        }
-    }
-
-    // -------------------------------------------------------------
-    // Client Window State
-    // -------------------------------------------------------------
-
-    private final class WindowState implements WindowManagerPolicy.WindowState {
-        final Session mSession;
-        final IWindow mClient;
-        WindowToken mToken;
-        WindowToken mRootToken;
-        AppWindowToken mAppToken;
-        AppWindowToken mTargetAppToken;
-        final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams();
-        final DeathRecipient mDeathRecipient;
-        final WindowState mAttachedWindow;
-        final ArrayList<WindowState> mChildWindows = new ArrayList<WindowState>();
-        final int mBaseLayer;
-        final int mSubLayer;
-        final boolean mLayoutAttached;
-        final boolean mIsImWindow;
-        final boolean mIsWallpaper;
-        final boolean mIsFloatingLayer;
-        int mViewVisibility;
-        boolean mPolicyVisibility = true;
-        boolean mPolicyVisibilityAfterAnim = true;
-        boolean mAppFreezing;
-        Surface mSurface;
-        boolean mReportDestroySurface;
-        boolean mSurfacePendingDestroy;
-        boolean mAttachedHidden;    // is our parent window hidden?
-        boolean mLastHidden;        // was this window last hidden?
-        boolean mWallpaperVisible;  // for wallpaper, what was last vis report?
-        int mRequestedWidth;
-        int mRequestedHeight;
-        int mLastRequestedWidth;
-        int mLastRequestedHeight;
-        int mLayer;
-        int mAnimLayer;
-        int mLastLayer;
-        boolean mHaveFrame;
-        boolean mObscured;
-        boolean mTurnOnScreen;
-
-        int mLayoutSeq = -1;
-        
-        Configuration mConfiguration = null;
-        
-        // Actual frame shown on-screen (may be modified by animation)
-        final Rect mShownFrame = new Rect();
-        final Rect mLastShownFrame = new Rect();
-
-        /**
-         * Set when we have changed the size of the surface, to know that
-         * we must tell them application to resize (and thus redraw itself).
-         */
-        boolean mSurfaceResized;
-        
-        /**
-         * Insets that determine the actually visible area
-         */
-        final Rect mVisibleInsets = new Rect();
-        final Rect mLastVisibleInsets = new Rect();
-        boolean mVisibleInsetsChanged;
-
-        /**
-         * Insets that are covered by system windows
-         */
-        final Rect mContentInsets = new Rect();
-        final Rect mLastContentInsets = new Rect();
-        boolean mContentInsetsChanged;
-
-        /**
-         * Set to true if we are waiting for this window to receive its
-         * given internal insets before laying out other windows based on it.
-         */
-        boolean mGivenInsetsPending;
-
-        /**
-         * These are the content insets that were given during layout for
-         * this window, to be applied to windows behind it.
-         */
-        final Rect mGivenContentInsets = new Rect();
-
-        /**
-         * These are the visible insets that were given during layout for
-         * this window, to be applied to windows behind it.
-         */
-        final Rect mGivenVisibleInsets = new Rect();
-
-        /**
-         * This is the given touchable area relative to the window frame, or null if none.
-         */
-        final Region mGivenTouchableRegion = new Region();
-
-        /**
-         * Flag indicating whether the touchable region should be adjusted by
-         * the visible insets; if false the area outside the visible insets is
-         * NOT touchable, so we must use those to adjust the frame during hit
-         * tests.
-         */
-        int mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
-
-        // Current transformation being applied.
-        boolean mHaveMatrix;
-        float mDsDx=1, mDtDx=0, mDsDy=0, mDtDy=1;
-        float mLastDsDx=1, mLastDtDx=0, mLastDsDy=0, mLastDtDy=1;
-        float mHScale=1, mVScale=1;
-        float mLastHScale=1, mLastVScale=1;
-        final Matrix mTmpMatrix = new Matrix();
-
-        // "Real" frame that the application sees.
-        final Rect mFrame = new Rect();
-        final Rect mLastFrame = new Rect();
-
-        final Rect mContainingFrame = new Rect();
-        final Rect mDisplayFrame = new Rect();
-        final Rect mContentFrame = new Rect();
-        final Rect mParentFrame = new Rect();
-        final Rect mVisibleFrame = new Rect();
-
-        boolean mContentChanged;
-
-        float mShownAlpha = 1;
-        float mAlpha = 1;
-        float mLastAlpha = 1;
-
-        // Set to true if, when the window gets displayed, it should perform
-        // an enter animation.
-        boolean mEnterAnimationPending;
-
-        // Currently running animation.
-        boolean mAnimating;
-        boolean mLocalAnimating;
-        Animation mAnimation;
-        boolean mAnimationIsEntrance;
-        boolean mHasTransformation;
-        boolean mHasLocalTransformation;
-        final Transformation mTransformation = new Transformation();
-
-        // If a window showing a wallpaper: the requested offset for the
-        // wallpaper; if a wallpaper window: the currently applied offset.
-        float mWallpaperX = -1;
-        float mWallpaperY = -1;
-
-        // If a window showing a wallpaper: what fraction of the offset
-        // range corresponds to a full virtual screen.
-        float mWallpaperXStep = -1;
-        float mWallpaperYStep = -1;
-
-        // Wallpaper windows: pixels offset based on above variables.
-        int mXOffset;
-        int mYOffset;
-
-        // This is set after IWindowSession.relayout() has been called at
-        // least once for the window.  It allows us to detect the situation
-        // where we don't yet have a surface, but should have one soon, so
-        // we can give the window focus before waiting for the relayout.
-        boolean mRelayoutCalled;
-
-        // This is set after the Surface has been created but before the
-        // window has been drawn.  During this time the surface is hidden.
-        boolean mDrawPending;
-
-        // This is set after the window has finished drawing for the first
-        // time but before its surface is shown.  The surface will be
-        // displayed when the next layout is run.
-        boolean mCommitDrawPending;
-
-        // This is set during the time after the window's drawing has been
-        // committed, and before its surface is actually shown.  It is used
-        // to delay showing the surface until all windows in a token are ready
-        // to be shown.
-        boolean mReadyToShow;
-
-        // Set when the window has been shown in the screen the first time.
-        boolean mHasDrawn;
-
-        // Currently running an exit animation?
-        boolean mExiting;
-
-        // Currently on the mDestroySurface list?
-        boolean mDestroying;
-
-        // Completely remove from window manager after exit animation?
-        boolean mRemoveOnExit;
-
-        // Set when the orientation is changing and this window has not yet
-        // been updated for the new orientation.
-        boolean mOrientationChanging;
-
-        // Is this window now (or just being) removed?
-        boolean mRemoved;
-
-        // Temp for keeping track of windows that have been removed when
-        // rebuilding window list.
-        boolean mRebuilding;
-
-        // For debugging, this is the last information given to the surface flinger.
-        boolean mSurfaceShown;
-        int mSurfaceX, mSurfaceY, mSurfaceW, mSurfaceH;
-        int mSurfaceLayer;
-        float mSurfaceAlpha;
-        
-        // Input channel and input window handle used by the input dispatcher.
-        InputWindowHandle mInputWindowHandle;
-        InputChannel mInputChannel;
-        
-        // Used to improve performance of toString()
-        String mStringNameCache;
-        CharSequence mLastTitle;
-        boolean mWasPaused;
-
-        WindowState(Session s, IWindow c, WindowToken token,
-               WindowState attachedWindow, WindowManager.LayoutParams a,
-               int viewVisibility) {
-            mSession = s;
-            mClient = c;
-            mToken = token;
-            mAttrs.copyFrom(a);
-            mViewVisibility = viewVisibility;
-            DeathRecipient deathRecipient = new DeathRecipient();
-            mAlpha = a.alpha;
-            if (localLOGV) Slog.v(
-                TAG, "Window " + this + " client=" + c.asBinder()
-                + " token=" + token + " (" + mAttrs.token + ")");
-            try {
-                c.asBinder().linkToDeath(deathRecipient, 0);
-            } catch (RemoteException e) {
-                mDeathRecipient = null;
-                mAttachedWindow = null;
-                mLayoutAttached = false;
-                mIsImWindow = false;
-                mIsWallpaper = false;
-                mIsFloatingLayer = false;
-                mBaseLayer = 0;
-                mSubLayer = 0;
-                return;
-            }
-            mDeathRecipient = deathRecipient;
-
-            if ((mAttrs.type >= FIRST_SUB_WINDOW &&
-                    mAttrs.type <= LAST_SUB_WINDOW)) {
-                // The multiplier here is to reserve space for multiple
-                // windows in the same type layer.
-                mBaseLayer = mPolicy.windowTypeToLayerLw(
-                        attachedWindow.mAttrs.type) * TYPE_LAYER_MULTIPLIER
-                        + TYPE_LAYER_OFFSET;
-                mSubLayer = mPolicy.subWindowTypeToLayerLw(a.type);
-                mAttachedWindow = attachedWindow;
-                if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + this + " to " + mAttachedWindow);
-                mAttachedWindow.mChildWindows.add(this);
-                mLayoutAttached = mAttrs.type !=
-                        WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
-                mIsImWindow = attachedWindow.mAttrs.type == TYPE_INPUT_METHOD
-                        || attachedWindow.mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
-                mIsWallpaper = attachedWindow.mAttrs.type == TYPE_WALLPAPER;
-                mIsFloatingLayer = mIsImWindow || mIsWallpaper;
-            } else {
-                // The multiplier here is to reserve space for multiple
-                // windows in the same type layer.
-                mBaseLayer = mPolicy.windowTypeToLayerLw(a.type)
-                        * TYPE_LAYER_MULTIPLIER
-                        + TYPE_LAYER_OFFSET;
-                mSubLayer = 0;
-                mAttachedWindow = null;
-                mLayoutAttached = false;
-                mIsImWindow = mAttrs.type == TYPE_INPUT_METHOD
-                        || mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
-                mIsWallpaper = mAttrs.type == TYPE_WALLPAPER;
-                mIsFloatingLayer = mIsImWindow || mIsWallpaper;
-            }
-
-            WindowState appWin = this;
-            while (appWin.mAttachedWindow != null) {
-                appWin = mAttachedWindow;
-            }
-            WindowToken appToken = appWin.mToken;
-            while (appToken.appWindowToken == null) {
-                WindowToken parent = mTokenMap.get(appToken.token);
-                if (parent == null || appToken == parent) {
-                    break;
-                }
-                appToken = parent;
-            }
-            mRootToken = appToken;
-            mAppToken = appToken.appWindowToken;
-
-            mSurface = null;
-            mRequestedWidth = 0;
-            mRequestedHeight = 0;
-            mLastRequestedWidth = 0;
-            mLastRequestedHeight = 0;
-            mXOffset = 0;
-            mYOffset = 0;
-            mLayer = 0;
-            mAnimLayer = 0;
-            mLastLayer = 0;
-            mInputWindowHandle = new InputWindowHandle(
-                    mAppToken != null ? mAppToken.mInputApplicationHandle : null, this);
-        }
-
-        void attach() {
-            if (localLOGV) Slog.v(
-                TAG, "Attaching " + this + " token=" + mToken
-                + ", list=" + mToken.windows);
-            mSession.windowAddedLocked();
-        }
-
-        public void computeFrameLw(Rect pf, Rect df, Rect cf, Rect vf) {
-            mHaveFrame = true;
-
-            final Rect container = mContainingFrame;
-            container.set(pf);
-
-            final Rect display = mDisplayFrame;
-            display.set(df);
-
-            if ((mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
-                container.intersect(mCompatibleScreenFrame);
-                if ((mAttrs.flags & FLAG_LAYOUT_NO_LIMITS) == 0) {
-                    display.intersect(mCompatibleScreenFrame);
-                }
-            }
-
-            final int pw = container.right - container.left;
-            final int ph = container.bottom - container.top;
-
-            int w,h;
-            if ((mAttrs.flags & mAttrs.FLAG_SCALED) != 0) {
-                w = mAttrs.width < 0 ? pw : mAttrs.width;
-                h = mAttrs.height< 0 ? ph : mAttrs.height;
-            } else {
-                w = mAttrs.width == mAttrs.MATCH_PARENT ? pw : mRequestedWidth;
-                h = mAttrs.height== mAttrs.MATCH_PARENT ? ph : mRequestedHeight;
-            }
-
-            if (!mParentFrame.equals(pf)) {
-                //Slog.i(TAG, "Window " + this + " content frame from " + mParentFrame
-                //        + " to " + pf);
-                mParentFrame.set(pf);
-                mContentChanged = true;
-            }
-
-            final Rect content = mContentFrame;
-            content.set(cf);
-
-            final Rect visible = mVisibleFrame;
-            visible.set(vf);
-
-            final Rect frame = mFrame;
-            final int fw = frame.width();
-            final int fh = frame.height();
-
-            //System.out.println("In: w=" + w + " h=" + h + " container=" +
-            //                   container + " x=" + mAttrs.x + " y=" + mAttrs.y);
-
-            Gravity.apply(mAttrs.gravity, w, h, container,
-                    (int) (mAttrs.x + mAttrs.horizontalMargin * pw),
-                    (int) (mAttrs.y + mAttrs.verticalMargin * ph), frame);
-
-            //System.out.println("Out: " + mFrame);
-
-            // Now make sure the window fits in the overall display.
-            Gravity.applyDisplay(mAttrs.gravity, df, frame);
-
-            // Make sure the content and visible frames are inside of the
-            // final window frame.
-            if (content.left < frame.left) content.left = frame.left;
-            if (content.top < frame.top) content.top = frame.top;
-            if (content.right > frame.right) content.right = frame.right;
-            if (content.bottom > frame.bottom) content.bottom = frame.bottom;
-            if (visible.left < frame.left) visible.left = frame.left;
-            if (visible.top < frame.top) visible.top = frame.top;
-            if (visible.right > frame.right) visible.right = frame.right;
-            if (visible.bottom > frame.bottom) visible.bottom = frame.bottom;
-
-            final Rect contentInsets = mContentInsets;
-            contentInsets.left = content.left-frame.left;
-            contentInsets.top = content.top-frame.top;
-            contentInsets.right = frame.right-content.right;
-            contentInsets.bottom = frame.bottom-content.bottom;
-
-            final Rect visibleInsets = mVisibleInsets;
-            visibleInsets.left = visible.left-frame.left;
-            visibleInsets.top = visible.top-frame.top;
-            visibleInsets.right = frame.right-visible.right;
-            visibleInsets.bottom = frame.bottom-visible.bottom;
-
-            if (mIsWallpaper && (fw != frame.width() || fh != frame.height())) {
-                updateWallpaperOffsetLocked(this, mDisplay.getWidth(),
-                        mDisplay.getHeight(), false);
-            }
-
-            if (localLOGV) {
-                //if ("com.google.android.youtube".equals(mAttrs.packageName)
-                //        && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
-                    Slog.v(TAG, "Resolving (mRequestedWidth="
-                            + mRequestedWidth + ", mRequestedheight="
-                            + mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph
-                            + "): frame=" + mFrame.toShortString()
-                            + " ci=" + contentInsets.toShortString()
-                            + " vi=" + visibleInsets.toShortString());
-                //}
-            }
-        }
-
-        public Rect getFrameLw() {
-            return mFrame;
-        }
-
-        public Rect getShownFrameLw() {
-            return mShownFrame;
-        }
-
-        public Rect getDisplayFrameLw() {
-            return mDisplayFrame;
-        }
-
-        public Rect getContentFrameLw() {
-            return mContentFrame;
-        }
-
-        public Rect getVisibleFrameLw() {
-            return mVisibleFrame;
-        }
-
-        public boolean getGivenInsetsPendingLw() {
-            return mGivenInsetsPending;
-        }
-
-        public Rect getGivenContentInsetsLw() {
-            return mGivenContentInsets;
-        }
-
-        public Rect getGivenVisibleInsetsLw() {
-            return mGivenVisibleInsets;
-        }
-
-        public WindowManager.LayoutParams getAttrs() {
-            return mAttrs;
-        }
-
-        public int getSurfaceLayer() {
-            return mLayer;
-        }
-
-        public IApplicationToken getAppToken() {
-            return mAppToken != null ? mAppToken.appToken : null;
-        }
-        
-        public long getInputDispatchingTimeoutNanos() {
-            return mAppToken != null
-                    ? mAppToken.inputDispatchingTimeoutNanos
-                    : DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
-        }
-
-        public boolean hasAppShownWindows() {
-            return mAppToken != null ? mAppToken.firstWindowDrawn : false;
-        }
-
-        public void setAnimation(Animation anim) {
-            if (localLOGV) Slog.v(
-                TAG, "Setting animation in " + this + ": " + anim);
-            mAnimating = false;
-            mLocalAnimating = false;
-            mAnimation = anim;
-            mAnimation.restrictDuration(MAX_ANIMATION_DURATION);
-            mAnimation.scaleCurrentDuration(mWindowAnimationScale);
-        }
-
-        public void clearAnimation() {
-            if (mAnimation != null) {
-                mAnimating = true;
-                mLocalAnimating = false;
-                mAnimation.cancel();
-                mAnimation = null;
-            }
-        }
-
-        Surface createSurfaceLocked() {
-            if (mSurface == null) {
-                mReportDestroySurface = false;
-                mSurfacePendingDestroy = false;
-                mDrawPending = true;
-                mCommitDrawPending = false;
-                mReadyToShow = false;
-                if (mAppToken != null) {
-                    mAppToken.allDrawn = false;
-                }
-
-                int flags = 0;
-
-                if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
-                    flags |= Surface.SECURE;
-                }
-                if (DEBUG_VISIBILITY) Slog.v(
-                    TAG, "Creating surface in session "
-                    + mSession.mSurfaceSession + " window " + this
-                    + " w=" + mFrame.width()
-                    + " h=" + mFrame.height() + " format="
-                    + mAttrs.format + " flags=" + flags);
-
-                int w = mFrame.width();
-                int h = mFrame.height();
-                if ((mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) {
-                    // for a scaled surface, we always want the requested
-                    // size.
-                    w = mRequestedWidth;
-                    h = mRequestedHeight;
-                }
-
-                // Something is wrong and SurfaceFlinger will not like this,
-                // try to revert to sane values
-                if (w <= 0) w = 1;
-                if (h <= 0) h = 1;
-
-                mSurfaceShown = false;
-                mSurfaceLayer = 0;
-                mSurfaceAlpha = 1;
-                mSurfaceX = 0;
-                mSurfaceY = 0;
-                mSurfaceW = w;
-                mSurfaceH = h;
-                try {
-                    final boolean isHwAccelerated = (mAttrs.flags &
-                            WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0;
-                    final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : mAttrs.format;
-                    if (isHwAccelerated && mAttrs.format == PixelFormat.OPAQUE) {
-                        flags |= Surface.OPAQUE;
-                    }
-                    mSurface = new Surface(
-                            mSession.mSurfaceSession, mSession.mPid,
-                            mAttrs.getTitle().toString(),
-                            0, w, h, format, flags);
-                    if (SHOW_TRANSACTIONS) Slog.i(TAG, "  CREATE SURFACE "
-                            + mSurface + " IN SESSION "
-                            + mSession.mSurfaceSession
-                            + ": pid=" + mSession.mPid + " format="
-                            + mAttrs.format + " flags=0x"
-                            + Integer.toHexString(flags)
-                            + " / " + this);
-                } catch (Surface.OutOfResourcesException e) {
-                    Slog.w(TAG, "OutOfResourcesException creating surface");
-                    reclaimSomeSurfaceMemoryLocked(this, "create");
-                    return null;
-                } catch (Exception e) {
-                    Slog.e(TAG, "Exception creating surface", e);
-                    return null;
-                }
-
-                if (localLOGV) Slog.v(
-                    TAG, "Got surface: " + mSurface
-                    + ", set left=" + mFrame.left + " top=" + mFrame.top
-                    + ", animLayer=" + mAnimLayer);
-                if (SHOW_TRANSACTIONS) {
-                    Slog.i(TAG, ">>> OPEN TRANSACTION createSurfaceLocked");
-                    logSurface(this, "CREATE pos=(" + mFrame.left + "," + mFrame.top + ") (" +
-                            mFrame.width() + "x" + mFrame.height() + "), layer=" +
-                            mAnimLayer + " HIDE", null);
-                }
-                Surface.openTransaction();
-                try {
-                    try {
-                        mSurfaceX = mFrame.left + mXOffset;
-                        mSurfaceY = mFrame.top + mYOffset;
-                        mSurface.setPosition(mSurfaceX, mSurfaceY);
-                        mSurfaceLayer = mAnimLayer;
-                        mSurface.setLayer(mAnimLayer);
-                        mSurfaceShown = false;
-                        mSurface.hide();
-                        if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_DITHER) != 0) {
-                            if (SHOW_TRANSACTIONS) logSurface(this, "DITHER", null);
-                            mSurface.setFlags(Surface.SURFACE_DITHER,
-                                    Surface.SURFACE_DITHER);
-                        }
-                    } catch (RuntimeException e) {
-                        Slog.w(TAG, "Error creating surface in " + w, e);
-                        reclaimSomeSurfaceMemoryLocked(this, "create-init");
-                    }
-                    mLastHidden = true;
-                } finally {
-                    Surface.closeTransaction();
-                    if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION createSurfaceLocked");
-                }
-                if (localLOGV) Slog.v(
-                        TAG, "Created surface " + this);
-            }
-            return mSurface;
-        }
-
-        void destroySurfaceLocked() {
-            if (mAppToken != null && this == mAppToken.startingWindow) {
-                mAppToken.startingDisplayed = false;
-            }
-
-            if (mSurface != null) {
-                mDrawPending = false;
-                mCommitDrawPending = false;
-                mReadyToShow = false;
-
-                int i = mChildWindows.size();
-                while (i > 0) {
-                    i--;
-                    WindowState c = mChildWindows.get(i);
-                    c.mAttachedHidden = true;
-                }
-
-                if (mReportDestroySurface) {
-                    mReportDestroySurface = false;
-                    mSurfacePendingDestroy = true;
-                    try {
-                        mClient.dispatchGetNewSurface();
-                        // We'll really destroy on the next time around.
-                        return;
-                    } catch (RemoteException e) {
-                    }
-                }
-
-                try {
-                    if (DEBUG_VISIBILITY) {
-                        RuntimeException e = null;
-                        if (!HIDE_STACK_CRAWLS) {
-                            e = new RuntimeException();
-                            e.fillInStackTrace();
-                        }
-                        Slog.w(TAG, "Window " + this + " destroying surface "
-                                + mSurface + ", session " + mSession, e);
-                    }
-                    if (SHOW_TRANSACTIONS) {
-                        RuntimeException e = null;
-                        if (!HIDE_STACK_CRAWLS) {
-                            e = new RuntimeException();
-                            e.fillInStackTrace();
-                        }
-                        if (SHOW_TRANSACTIONS) logSurface(this, "DESTROY", e);
-                    }
-                    mSurface.destroy();
-                } catch (RuntimeException e) {
-                    Slog.w(TAG, "Exception thrown when destroying Window " + this
-                        + " surface " + mSurface + " session " + mSession
-                        + ": " + e.toString());
-                }
-
-                mSurfaceShown = false;
-                mSurface = null;
-            }
-        }
-
-        boolean finishDrawingLocked() {
-            if (mDrawPending) {
-                if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION) Slog.v(
-                    TAG, "finishDrawingLocked: " + mSurface);
-                mCommitDrawPending = true;
-                mDrawPending = false;
-                return true;
-            }
-            return false;
-        }
-
-        // This must be called while inside a transaction.
-        boolean commitFinishDrawingLocked(long currentTime) {
-            //Slog.i(TAG, "commitFinishDrawingLocked: " + mSurface);
-            if (!mCommitDrawPending) {
-                return false;
-            }
-            mCommitDrawPending = false;
-            mReadyToShow = true;
-            final boolean starting = mAttrs.type == TYPE_APPLICATION_STARTING;
-            final AppWindowToken atoken = mAppToken;
-            if (atoken == null || atoken.allDrawn || starting) {
-                performShowLocked();
-            }
-            return true;
-        }
-
-        // This must be called while inside a transaction.
-        boolean performShowLocked() {
-            if (DEBUG_VISIBILITY) {
-                RuntimeException e = null;
-                if (!HIDE_STACK_CRAWLS) {
-                    e = new RuntimeException();
-                    e.fillInStackTrace();
-                }
-                Slog.v(TAG, "performShow on " + this
-                        + ": readyToShow=" + mReadyToShow + " readyForDisplay=" + isReadyForDisplay()
-                        + " starting=" + (mAttrs.type == TYPE_APPLICATION_STARTING), e);
-            }
-            if (mReadyToShow && isReadyForDisplay()) {
-                if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION) logSurface(this,
-                        "SHOW (performShowLocked)", null);
-                if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + this
-                        + " during animation: policyVis=" + mPolicyVisibility
-                        + " attHidden=" + mAttachedHidden
-                        + " tok.hiddenRequested="
-                        + (mAppToken != null ? mAppToken.hiddenRequested : false)
-                        + " tok.hidden="
-                        + (mAppToken != null ? mAppToken.hidden : false)
-                        + " animating=" + mAnimating
-                        + " tok animating="
-                        + (mAppToken != null ? mAppToken.animating : false));
-                if (!showSurfaceRobustlyLocked(this)) {
-                    return false;
-                }
-                mLastAlpha = -1;
-                mHasDrawn = true;
-                mLastHidden = false;
-                mReadyToShow = false;
-                enableScreenIfNeededLocked();
-
-                applyEnterAnimationLocked(this);
-
-                int i = mChildWindows.size();
-                while (i > 0) {
-                    i--;
-                    WindowState c = mChildWindows.get(i);
-                    if (c.mAttachedHidden) {
-                        c.mAttachedHidden = false;
-                        if (c.mSurface != null) {
-                            c.performShowLocked();
-                            // It hadn't been shown, which means layout not
-                            // performed on it, so now we want to make sure to
-                            // do a layout.  If called from within the transaction
-                            // loop, this will cause it to restart with a new
-                            // layout.
-                            mLayoutNeeded = true;
-                        }
-                    }
-                }
-
-                if (mAttrs.type != TYPE_APPLICATION_STARTING
-                        && mAppToken != null) {
-                    mAppToken.firstWindowDrawn = true;
-
-                    if (mAppToken.startingData != null) {
-                        if (DEBUG_STARTING_WINDOW || DEBUG_ANIM) Slog.v(TAG,
-                                "Finish starting " + mToken
-                                + ": first real window is shown, no animation");
-                        // If this initial window is animating, stop it -- we
-                        // will do an animation to reveal it from behind the
-                        // starting window, so there is no need for it to also
-                        // be doing its own stuff.
-                        if (mAnimation != null) {
-                            mAnimation.cancel();
-                            mAnimation = null;
-                            // Make sure we clean up the animation.
-                            mAnimating = true;
-                        }
-                        mFinishedStarting.add(mAppToken);
-                        mH.sendEmptyMessage(H.FINISHED_STARTING);
-                    }
-                    mAppToken.updateReportedVisibilityLocked();
-                }
-            }
-            return true;
-        }
-
-        // This must be called while inside a transaction.  Returns true if
-        // there is more animation to run.
-        boolean stepAnimationLocked(long currentTime, int dw, int dh) {
-            if (!mDisplayFrozen && mPolicy.isScreenOn()) {
-                // We will run animations as long as the display isn't frozen.
-
-                if (!mDrawPending && !mCommitDrawPending && mAnimation != null) {
-                    mHasTransformation = true;
-                    mHasLocalTransformation = true;
-                    if (!mLocalAnimating) {
-                        if (DEBUG_ANIM) Slog.v(
-                            TAG, "Starting animation in " + this +
-                            " @ " + currentTime + ": ww=" + mFrame.width() + " wh=" + mFrame.height() +
-                            " dw=" + dw + " dh=" + dh + " scale=" + mWindowAnimationScale);
-                        mAnimation.initialize(mFrame.width(), mFrame.height(), dw, dh);
-                        mAnimation.setStartTime(currentTime);
-                        mLocalAnimating = true;
-                        mAnimating = true;
-                    }
-                    mTransformation.clear();
-                    final boolean more = mAnimation.getTransformation(
-                        currentTime, mTransformation);
-                    if (DEBUG_ANIM) Slog.v(
-                        TAG, "Stepped animation in " + this +
-                        ": more=" + more + ", xform=" + mTransformation);
-                    if (more) {
-                        // we're not done!
-                        return true;
-                    }
-                    if (DEBUG_ANIM) Slog.v(
-                        TAG, "Finished animation in " + this +
-                        " @ " + currentTime);
-
-                    if (mAnimation != null) {
-                        mAnimation.cancel();
-                        mAnimation = null;
-                    }
-                    //WindowManagerService.this.dump();
-                }
-                mHasLocalTransformation = false;
-                if ((!mLocalAnimating || mAnimationIsEntrance) && mAppToken != null
-                        && mAppToken.animation != null) {
-                    // When our app token is animating, we kind-of pretend like
-                    // we are as well.  Note the mLocalAnimating mAnimationIsEntrance
-                    // part of this check means that we will only do this if
-                    // our window is not currently exiting, or it is not
-                    // locally animating itself.  The idea being that one that
-                    // is exiting and doing a local animation should be removed
-                    // once that animation is done.
-                    mAnimating = true;
-                    mHasTransformation = true;
-                    mTransformation.clear();
-                    return false;
-                } else if (mHasTransformation) {
-                    // Little trick to get through the path below to act like
-                    // we have finished an animation.
-                    mAnimating = true;
-                } else if (isAnimating()) {
-                    mAnimating = true;
-                }
-            } else if (mAnimation != null) {
-                // If the display is frozen, and there is a pending animation,
-                // clear it and make sure we run the cleanup code.
-                mAnimating = true;
-                mLocalAnimating = true;
-                mAnimation.cancel();
-                mAnimation = null;
-            }
-
-            if (!mAnimating && !mLocalAnimating) {
-                return false;
-            }
-
-            if (DEBUG_ANIM) Slog.v(
-                TAG, "Animation done in " + this + ": exiting=" + mExiting
-                + ", reportedVisible="
-                + (mAppToken != null ? mAppToken.reportedVisible : false));
-
-            mAnimating = false;
-            mLocalAnimating = false;
-            if (mAnimation != null) {
-                mAnimation.cancel();
-                mAnimation = null;
-            }
-            mAnimLayer = mLayer;
-            if (mIsImWindow) {
-                mAnimLayer += mInputMethodAnimLayerAdjustment;
-            } else if (mIsWallpaper) {
-                mAnimLayer += mWallpaperAnimLayerAdjustment;
-            }
-            if (DEBUG_LAYERS) Slog.v(TAG, "Stepping win " + this
-                    + " anim layer: " + mAnimLayer);
-            mHasTransformation = false;
-            mHasLocalTransformation = false;
-            if (mPolicyVisibility != mPolicyVisibilityAfterAnim) {
-                if (DEBUG_VISIBILITY) {
-                    Slog.v(TAG, "Policy visibility changing after anim in " + this + ": "
-                            + mPolicyVisibilityAfterAnim);
-                }
-                mPolicyVisibility = mPolicyVisibilityAfterAnim;
-                if (!mPolicyVisibility) {
-                    if (mCurrentFocus == this) {
-                        mFocusMayChange = true;
-                    }
-                    // Window is no longer visible -- make sure if we were waiting
-                    // for it to be displayed before enabling the display, that
-                    // we allow the display to be enabled now.
-                    enableScreenIfNeededLocked();
-                }
-            }
-            mTransformation.clear();
-            if (mHasDrawn
-                    && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
-                    && mAppToken != null
-                    && mAppToken.firstWindowDrawn
-                    && mAppToken.startingData != null) {
-                if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Finish starting "
-                        + mToken + ": first real window done animating");
-                mFinishedStarting.add(mAppToken);
-                mH.sendEmptyMessage(H.FINISHED_STARTING);
-            }
-
-            finishExit();
-
-            if (mAppToken != null) {
-                mAppToken.updateReportedVisibilityLocked();
-            }
-
-            return false;
-        }
-
-        void finishExit() {
-            if (DEBUG_ANIM) Slog.v(
-                    TAG, "finishExit in " + this
-                    + ": exiting=" + mExiting
-                    + " remove=" + mRemoveOnExit
-                    + " windowAnimating=" + isWindowAnimating());
-
-            final int N = mChildWindows.size();
-            for (int i=0; i<N; i++) {
-                mChildWindows.get(i).finishExit();
-            }
-
-            if (!mExiting) {
-                return;
-            }
-
-            if (isWindowAnimating()) {
-                return;
-            }
-
-            if (localLOGV) Slog.v(
-                    TAG, "Exit animation finished in " + this
-                    + ": remove=" + mRemoveOnExit);
-            if (mSurface != null) {
-                mDestroySurface.add(this);
-                mDestroying = true;
-                if (SHOW_TRANSACTIONS) logSurface(this, "HIDE (finishExit)", null);
-                mSurfaceShown = false;
-                try {
-                    mSurface.hide();
-                } catch (RuntimeException e) {
-                    Slog.w(TAG, "Error hiding surface in " + this, e);
-                }
-                mLastHidden = true;
-            }
-            mExiting = false;
-            if (mRemoveOnExit) {
-                mPendingRemove.add(this);
-                mRemoveOnExit = false;
-            }
-        }
-
-        boolean isIdentityMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
-            if (dsdx < .99999f || dsdx > 1.00001f) return false;
-            if (dtdy < .99999f || dtdy > 1.00001f) return false;
-            if (dtdx < -.000001f || dtdx > .000001f) return false;
-            if (dsdy < -.000001f || dsdy > .000001f) return false;
-            return true;
-        }
-
-        void computeShownFrameLocked() {
-            final boolean selfTransformation = mHasLocalTransformation;
-            Transformation attachedTransformation =
-                    (mAttachedWindow != null && mAttachedWindow.mHasLocalTransformation)
-                    ? mAttachedWindow.mTransformation : null;
-            Transformation appTransformation =
-                    (mAppToken != null && mAppToken.hasTransformation)
-                    ? mAppToken.transformation : null;
-
-            // Wallpapers are animated based on the "real" window they
-            // are currently targeting.
-            if (mAttrs.type == TYPE_WALLPAPER && mLowerWallpaperTarget == null
-                    && mWallpaperTarget != null) {
-                if (mWallpaperTarget.mHasLocalTransformation &&
-                        mWallpaperTarget.mAnimation != null &&
-                        !mWallpaperTarget.mAnimation.getDetachWallpaper()) {
-                    attachedTransformation = mWallpaperTarget.mTransformation;
-                    if (DEBUG_WALLPAPER && attachedTransformation != null) {
-                        Slog.v(TAG, "WP target attached xform: " + attachedTransformation);
-                    }
-                }
-                if (mWallpaperTarget.mAppToken != null &&
-                        mWallpaperTarget.mAppToken.hasTransformation &&
-                        mWallpaperTarget.mAppToken.animation != null &&
-                        !mWallpaperTarget.mAppToken.animation.getDetachWallpaper()) {
-                    appTransformation = mWallpaperTarget.mAppToken.transformation;
-                    if (DEBUG_WALLPAPER && appTransformation != null) {
-                        Slog.v(TAG, "WP target app xform: " + appTransformation);
-                    }
-                }
-            }
-
-            final boolean screenAnimation = mScreenRotationAnimation != null
-                    && mScreenRotationAnimation.isAnimating();
-            if (selfTransformation || attachedTransformation != null
-                    || appTransformation != null || screenAnimation) {
-                // cache often used attributes locally
-                final Rect frame = mFrame;
-                final float tmpFloats[] = mTmpFloats;
-                final Matrix tmpMatrix = mTmpMatrix;
-
-                // Compute the desired transformation.
-                tmpMatrix.setTranslate(0, 0);
-                if (selfTransformation) {
-                    tmpMatrix.postConcat(mTransformation.getMatrix());
-                }
-                tmpMatrix.postTranslate(frame.left + mXOffset, frame.top + mYOffset);
-                if (attachedTransformation != null) {
-                    tmpMatrix.postConcat(attachedTransformation.getMatrix());
-                }
-                if (appTransformation != null) {
-                    tmpMatrix.postConcat(appTransformation.getMatrix());
-                }
-                if (screenAnimation) {
-                    tmpMatrix.postConcat(
-                            mScreenRotationAnimation.getEnterTransformation().getMatrix());
-                }
-
-                // "convert" it into SurfaceFlinger's format
-                // (a 2x2 matrix + an offset)
-                // Here we must not transform the position of the surface
-                // since it is already included in the transformation.
-                //Slog.i(TAG, "Transform: " + matrix);
-
-                mHaveMatrix = true;
-                tmpMatrix.getValues(tmpFloats);
-                mDsDx = tmpFloats[Matrix.MSCALE_X];
-                mDtDx = tmpFloats[Matrix.MSKEW_Y];
-                mDsDy = tmpFloats[Matrix.MSKEW_X];
-                mDtDy = tmpFloats[Matrix.MSCALE_Y];
-                int x = (int)tmpFloats[Matrix.MTRANS_X];
-                int y = (int)tmpFloats[Matrix.MTRANS_Y];
-                int w = frame.width();
-                int h = frame.height();
-                mShownFrame.set(x, y, x+w, y+h);
-
-                // Now set the alpha...  but because our current hardware
-                // can't do alpha transformation on a non-opaque surface,
-                // turn it off if we are running an animation that is also
-                // transforming since it is more important to have that
-                // animation be smooth.
-                mShownAlpha = mAlpha;
-                if (!mLimitedAlphaCompositing
-                        || (!PixelFormat.formatHasAlpha(mAttrs.format)
-                        || (isIdentityMatrix(mDsDx, mDtDx, mDsDy, mDtDy)
-                                && x == frame.left && y == frame.top))) {
-                    //Slog.i(TAG, "Applying alpha transform");
-                    if (selfTransformation) {
-                        mShownAlpha *= mTransformation.getAlpha();
-                    }
-                    if (attachedTransformation != null) {
-                        mShownAlpha *= attachedTransformation.getAlpha();
-                    }
-                    if (appTransformation != null) {
-                        mShownAlpha *= appTransformation.getAlpha();
-                    }
-                    if (screenAnimation) {
-                        mShownAlpha *=
-                            mScreenRotationAnimation.getEnterTransformation().getAlpha();
-                    }
-                } else {
-                    //Slog.i(TAG, "Not applying alpha transform");
-                }
-
-                if (localLOGV) Slog.v(
-                    TAG, "Continuing animation in " + this +
-                    ": " + mShownFrame +
-                    ", alpha=" + mTransformation.getAlpha());
-                return;
-            }
-
-            mShownFrame.set(mFrame);
-            if (mXOffset != 0 || mYOffset != 0) {
-                mShownFrame.offset(mXOffset, mYOffset);
-            }
-            mShownAlpha = mAlpha;
-            mHaveMatrix = false;
-            mDsDx = 1;
-            mDtDx = 0;
-            mDsDy = 0;
-            mDtDy = 1;
-        }
-
-        /**
-         * Is this window visible?  It is not visible if there is no
-         * surface, or we are in the process of running an exit animation
-         * that will remove the surface, or its app token has been hidden.
-         */
-        public boolean isVisibleLw() {
-            final AppWindowToken atoken = mAppToken;
-            return mSurface != null && mPolicyVisibility && !mAttachedHidden
-                    && (atoken == null || !atoken.hiddenRequested)
-                    && !mExiting && !mDestroying;
-        }
-
-        /**
-         * Like {@link #isVisibleLw}, but also counts a window that is currently
-         * "hidden" behind the keyguard as visible.  This allows us to apply
-         * things like window flags that impact the keyguard.
-         * XXX I am starting to think we need to have ANOTHER visibility flag
-         * for this "hidden behind keyguard" state rather than overloading
-         * mPolicyVisibility.  Ungh.
-         */
-        public boolean isVisibleOrBehindKeyguardLw() {
-            final AppWindowToken atoken = mAppToken;
-            return mSurface != null && !mAttachedHidden
-                    && (atoken == null ? mPolicyVisibility : !atoken.hiddenRequested)
-                    && !mDrawPending && !mCommitDrawPending
-                    && !mExiting && !mDestroying;
-        }
-
-        /**
-         * Is this window visible, ignoring its app token?  It is not visible
-         * if there is no surface, or we are in the process of running an exit animation
-         * that will remove the surface.
-         */
-        public boolean isWinVisibleLw() {
-            final AppWindowToken atoken = mAppToken;
-            return mSurface != null && mPolicyVisibility && !mAttachedHidden
-                    && (atoken == null || !atoken.hiddenRequested || atoken.animating)
-                    && !mExiting && !mDestroying;
-        }
-
-        /**
-         * The same as isVisible(), but follows the current hidden state of
-         * the associated app token, not the pending requested hidden state.
-         */
-        boolean isVisibleNow() {
-            return mSurface != null && mPolicyVisibility && !mAttachedHidden
-                    && !mRootToken.hidden && !mExiting && !mDestroying;
-        }
-
-        /**
-         * Can this window possibly be a drag/drop target?  The test here is
-         * a combination of the above "visible now" with the check that the
-         * Input Manager uses when discarding windows from input consideration.
-         */
-        boolean isPotentialDragTarget() {
-            return isVisibleNow() && (mInputChannel != null) && !mRemoved;
-        }
-
-        /**
-         * Same as isVisible(), but we also count it as visible between the
-         * call to IWindowSession.add() and the first relayout().
-         */
-        boolean isVisibleOrAdding() {
-            final AppWindowToken atoken = mAppToken;
-            return ((mSurface != null && !mReportDestroySurface)
-                            || (!mRelayoutCalled && mViewVisibility == View.VISIBLE))
-                    && mPolicyVisibility && !mAttachedHidden
-                    && (atoken == null || !atoken.hiddenRequested)
-                    && !mExiting && !mDestroying;
-        }
-
-        /**
-         * Is this window currently on-screen?  It is on-screen either if it
-         * is visible or it is currently running an animation before no longer
-         * being visible.
-         */
-        boolean isOnScreen() {
-            final AppWindowToken atoken = mAppToken;
-            if (atoken != null) {
-                return mSurface != null && mPolicyVisibility && !mDestroying
-                        && ((!mAttachedHidden && !atoken.hiddenRequested)
-                                || mAnimation != null || atoken.animation != null);
-            } else {
-                return mSurface != null && mPolicyVisibility && !mDestroying
-                        && (!mAttachedHidden || mAnimation != null);
-            }
-        }
-
-        /**
-         * Like isOnScreen(), but we don't return true if the window is part
-         * of a transition that has not yet been started.
-         */
-        boolean isReadyForDisplay() {
-            if (mRootToken.waitingToShow &&
-                    mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
-                return false;
-            }
-            final AppWindowToken atoken = mAppToken;
-            final boolean animating = atoken != null
-                    ? (atoken.animation != null) : false;
-            return mSurface != null && mPolicyVisibility && !mDestroying
-                    && ((!mAttachedHidden && mViewVisibility == View.VISIBLE
-                                    && !mRootToken.hidden)
-                            || mAnimation != null || animating);
-        }
-
-        /** Is the window or its container currently animating? */
-        boolean isAnimating() {
-            final WindowState attached = mAttachedWindow;
-            final AppWindowToken atoken = mAppToken;
-            return mAnimation != null
-                    || (attached != null && attached.mAnimation != null)
-                    || (atoken != null &&
-                            (atoken.animation != null
-                                    || atoken.inPendingTransaction));
-        }
-
-        /** Is this window currently animating? */
-        boolean isWindowAnimating() {
-            return mAnimation != null;
-        }
-
-        /**
-         * Like isOnScreen, but returns false if the surface hasn't yet
-         * been drawn.
-         */
-        public boolean isDisplayedLw() {
-            final AppWindowToken atoken = mAppToken;
-            return mSurface != null && mPolicyVisibility && !mDestroying
-                && !mDrawPending && !mCommitDrawPending
-                && ((!mAttachedHidden &&
-                        (atoken == null || !atoken.hiddenRequested))
-                        || mAnimating);
-        }
-
-        /**
-         * Returns true if the window has a surface that it has drawn a
-         * complete UI in to.
-         */
-        public boolean isDrawnLw() {
-            final AppWindowToken atoken = mAppToken;
-            return mSurface != null && !mDestroying
-                && !mDrawPending && !mCommitDrawPending;
-        }
-
-        /**
-         * Return true if the window is opaque and fully drawn.  This indicates
-         * it may obscure windows behind it.
-         */
-        boolean isOpaqueDrawn() {
-            return (mAttrs.format == PixelFormat.OPAQUE
-                            || mAttrs.type == TYPE_WALLPAPER)
-                    && mSurface != null && mAnimation == null
-                    && (mAppToken == null || mAppToken.animation == null)
-                    && !mDrawPending && !mCommitDrawPending;
-        }
-
-        /**
-         * Return whether this window is wanting to have a translation
-         * animation applied to it for an in-progress move.  (Only makes
-         * sense to call from performLayoutAndPlaceSurfacesLockedInner().)
-         */
-        boolean shouldAnimateMove() {
-            return mContentChanged && !mExiting && !mLastHidden && !mDisplayFrozen
-                    && (mFrame.top != mLastFrame.top
-                            || mFrame.left != mLastFrame.left)
-                    && (mAttachedWindow == null || !mAttachedWindow.shouldAnimateMove())
-                    && mPolicy.isScreenOn();
-        }
-
-        boolean needsBackgroundFiller(int screenWidth, int screenHeight) {
-            return
-                 // only if the application is requesting compatible window
-                 (mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0 &&
-                 // only if it's visible
-                 mHasDrawn && mViewVisibility == View.VISIBLE &&
-                 // and only if the application fills the compatible screen
-                 mFrame.left <= mCompatibleScreenFrame.left &&
-                 mFrame.top <= mCompatibleScreenFrame.top &&
-                 mFrame.right >= mCompatibleScreenFrame.right &&
-                 mFrame.bottom >= mCompatibleScreenFrame.bottom;
-        }
-
-        boolean isFullscreen(int screenWidth, int screenHeight) {
-            return mFrame.left <= 0 && mFrame.top <= 0 &&
-                    mFrame.right >= screenWidth && mFrame.bottom >= screenHeight;
-        }
-
-        void removeLocked() {
-            disposeInputChannel();
-            
-            if (mAttachedWindow != null) {
-                if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing " + this + " from " + mAttachedWindow);
-                mAttachedWindow.mChildWindows.remove(this);
-            }
-            destroySurfaceLocked();
-            mSession.windowRemovedLocked();
-            try {
-                mClient.asBinder().unlinkToDeath(mDeathRecipient, 0);
-            } catch (RuntimeException e) {
-                // Ignore if it has already been removed (usually because
-                // we are doing this as part of processing a death note.)
-            }
-        }
-        
-        void disposeInputChannel() {
-            if (mInputChannel != null) {
-                mInputManager.unregisterInputChannel(mInputChannel);
-                
-                mInputChannel.dispose();
-                mInputChannel = null;
-            }
-        }
-
-        private class DeathRecipient implements IBinder.DeathRecipient {
-            public void binderDied() {
-                try {
-                    synchronized(mWindowMap) {
-                        WindowState win = windowForClientLocked(mSession, mClient, false);
-                        Slog.i(TAG, "WIN DEATH: " + win);
-                        if (win != null) {
-                            removeWindowLocked(mSession, win);
-                        }
-                    }
-                } catch (IllegalArgumentException ex) {
-                    // This will happen if the window has already been
-                    // removed.
-                }
-            }
-        }
-
-        /** Returns true if this window desires key events. */
-        public final boolean canReceiveKeys() {
-            return     isVisibleOrAdding()
-                    && (mViewVisibility == View.VISIBLE)
-                    && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0);
-        }
-
-        public boolean hasDrawnLw() {
-            return mHasDrawn;
-        }
-
-        public boolean showLw(boolean doAnimation) {
-            return showLw(doAnimation, true);
-        }
-
-        boolean showLw(boolean doAnimation, boolean requestAnim) {
-            if (mPolicyVisibility && mPolicyVisibilityAfterAnim) {
-                return false;
-            }
-            if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility true: " + this);
-            if (doAnimation) {
-                if (DEBUG_VISIBILITY) Slog.v(TAG, "doAnimation: mPolicyVisibility="
-                        + mPolicyVisibility + " mAnimation=" + mAnimation);
-                if (mDisplayFrozen || !mPolicy.isScreenOn()) {
-                    doAnimation = false;
-                } else if (mPolicyVisibility && mAnimation == null) {
-                    // Check for the case where we are currently visible and
-                    // not animating; we do not want to do animation at such a
-                    // point to become visible when we already are.
-                    doAnimation = false;
-                }
-            }
-            mPolicyVisibility = true;
-            mPolicyVisibilityAfterAnim = true;
-            if (doAnimation) {
-                applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_ENTER, true);
-            }
-            if (requestAnim) {
-                requestAnimationLocked(0);
-            }
-            return true;
-        }
-
-        public boolean hideLw(boolean doAnimation) {
-            return hideLw(doAnimation, true);
-        }
-
-        boolean hideLw(boolean doAnimation, boolean requestAnim) {
-            if (doAnimation) {
-                if (mDisplayFrozen || !mPolicy.isScreenOn()) {
-                    doAnimation = false;
-                }
-            }
-            boolean current = doAnimation ? mPolicyVisibilityAfterAnim
-                    : mPolicyVisibility;
-            if (!current) {
-                return false;
-            }
-            if (doAnimation) {
-                applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_EXIT, false);
-                if (mAnimation == null) {
-                    doAnimation = false;
-                }
-            }
-            if (doAnimation) {
-                mPolicyVisibilityAfterAnim = false;
-            } else {
-                if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility false: " + this);
-                mPolicyVisibilityAfterAnim = false;
-                mPolicyVisibility = false;
-                // Window is no longer visible -- make sure if we were waiting
-                // for it to be displayed before enabling the display, that
-                // we allow the display to be enabled now.
-                enableScreenIfNeededLocked();
-                if (mCurrentFocus == this) {
-                    mFocusMayChange = true;
-                }
-            }
-            if (requestAnim) {
-                requestAnimationLocked(0);
-            }
-            return true;
-        }
-
-        public void getTouchableRegion(Region outRegion) {
-            final Rect frame = mFrame;
-            switch (mTouchableInsets) {
-                default:
-                case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME:
-                    outRegion.set(frame);
-                    break;
-                case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT: {
-                    final Rect inset = mGivenContentInsets;
-                    outRegion.set(
-                            frame.left + inset.left, frame.top + inset.top,
-                            frame.right - inset.right, frame.bottom - inset.bottom);
-                    break;
-                }
-                case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE: {
-                    final Rect inset = mGivenVisibleInsets;
-                    outRegion.set(
-                            frame.left + inset.left, frame.top + inset.top,
-                            frame.right - inset.right, frame.bottom - inset.bottom);
-                    break;
-                }
-                case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION: {
-                    final Region givenTouchableRegion = mGivenTouchableRegion;
-                    outRegion.set(givenTouchableRegion);
-                    outRegion.translate(frame.left, frame.top);
-                    break;
-                }
-            }
-        }
-
-        void dump(PrintWriter pw, String prefix) {
-            pw.print(prefix); pw.print("mSession="); pw.print(mSession);
-                    pw.print(" mClient="); pw.println(mClient.asBinder());
-            pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs);
-            if (mAttachedWindow != null || mLayoutAttached) {
-                pw.print(prefix); pw.print("mAttachedWindow="); pw.print(mAttachedWindow);
-                        pw.print(" mLayoutAttached="); pw.println(mLayoutAttached);
-            }
-            if (mIsImWindow || mIsWallpaper || mIsFloatingLayer) {
-                pw.print(prefix); pw.print("mIsImWindow="); pw.print(mIsImWindow);
-                        pw.print(" mIsWallpaper="); pw.print(mIsWallpaper);
-                        pw.print(" mIsFloatingLayer="); pw.print(mIsFloatingLayer);
-                        pw.print(" mWallpaperVisible="); pw.println(mWallpaperVisible);
-            }
-            pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer);
-                    pw.print(" mSubLayer="); pw.print(mSubLayer);
-                    pw.print(" mAnimLayer="); pw.print(mLayer); pw.print("+");
-                    pw.print((mTargetAppToken != null ? mTargetAppToken.animLayerAdjustment
-                          : (mAppToken != null ? mAppToken.animLayerAdjustment : 0)));
-                    pw.print("="); pw.print(mAnimLayer);
-                    pw.print(" mLastLayer="); pw.println(mLastLayer);
-            if (mSurface != null) {
-                pw.print(prefix); pw.print("mSurface="); pw.println(mSurface);
-                pw.print(prefix); pw.print("Surface: shown="); pw.print(mSurfaceShown);
-                        pw.print(" layer="); pw.print(mSurfaceLayer);
-                        pw.print(" alpha="); pw.print(mSurfaceAlpha);
-                        pw.print(" rect=("); pw.print(mSurfaceX);
-                        pw.print(","); pw.print(mSurfaceY);
-                        pw.print(") "); pw.print(mSurfaceW);
-                        pw.print(" x "); pw.println(mSurfaceH);
-            }
-            pw.print(prefix); pw.print("mToken="); pw.println(mToken);
-            pw.print(prefix); pw.print("mRootToken="); pw.println(mRootToken);
-            if (mAppToken != null) {
-                pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken);
-            }
-            if (mTargetAppToken != null) {
-                pw.print(prefix); pw.print("mTargetAppToken="); pw.println(mTargetAppToken);
-            }
-            pw.print(prefix); pw.print("mViewVisibility=0x");
-                    pw.print(Integer.toHexString(mViewVisibility));
-                    pw.print(" mLastHidden="); pw.print(mLastHidden);
-                    pw.print(" mHaveFrame="); pw.print(mHaveFrame);
-                    pw.print(" mObscured="); pw.println(mObscured);
-            if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || mAttachedHidden) {
-                pw.print(prefix); pw.print("mPolicyVisibility=");
-                        pw.print(mPolicyVisibility);
-                        pw.print(" mPolicyVisibilityAfterAnim=");
-                        pw.print(mPolicyVisibilityAfterAnim);
-                        pw.print(" mAttachedHidden="); pw.println(mAttachedHidden);
-            }
-            if (!mRelayoutCalled) {
-                pw.print(prefix); pw.print("mRelayoutCalled="); pw.println(mRelayoutCalled);
-            }
-            pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth);
-                    pw.print(" h="); pw.print(mRequestedHeight);
-                    pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
-            if (mXOffset != 0 || mYOffset != 0) {
-                pw.print(prefix); pw.print("Offsets x="); pw.print(mXOffset);
-                        pw.print(" y="); pw.println(mYOffset);
-            }
-            pw.print(prefix); pw.print("mGivenContentInsets=");
-                    mGivenContentInsets.printShortString(pw);
-                    pw.print(" mGivenVisibleInsets=");
-                    mGivenVisibleInsets.printShortString(pw);
-                    pw.println();
-            if (mTouchableInsets != 0 || mGivenInsetsPending) {
-                pw.print(prefix); pw.print("mTouchableInsets="); pw.print(mTouchableInsets);
-                        pw.print(" mGivenInsetsPending="); pw.println(mGivenInsetsPending);
-            }
-            pw.print(prefix); pw.print("mConfiguration="); pw.println(mConfiguration);
-            pw.print(prefix); pw.print("mShownFrame=");
-                    mShownFrame.printShortString(pw);
-                    pw.print(" last="); mLastShownFrame.printShortString(pw);
-                    pw.println();
-            pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw);
-                    pw.print(" last="); mLastFrame.printShortString(pw);
-                    pw.println();
-            pw.print(prefix); pw.print("mContainingFrame=");
-                    mContainingFrame.printShortString(pw);
-                    pw.print(" mParentFrame=");
-                    mParentFrame.printShortString(pw);
-                    pw.print(" mDisplayFrame=");
-                    mDisplayFrame.printShortString(pw);
-                    pw.println();
-            pw.print(prefix); pw.print("mContentFrame="); mContentFrame.printShortString(pw);
-                    pw.print(" mVisibleFrame="); mVisibleFrame.printShortString(pw);
-                    pw.println();
-            pw.print(prefix); pw.print("mContentInsets="); mContentInsets.printShortString(pw);
-                    pw.print(" last="); mLastContentInsets.printShortString(pw);
-                    pw.print(" mVisibleInsets="); mVisibleInsets.printShortString(pw);
-                    pw.print(" last="); mLastVisibleInsets.printShortString(pw);
-                    pw.println();
-            if (mAnimating || mLocalAnimating || mAnimationIsEntrance
-                    || mAnimation != null) {
-                pw.print(prefix); pw.print("mAnimating="); pw.print(mAnimating);
-                        pw.print(" mLocalAnimating="); pw.print(mLocalAnimating);
-                        pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance);
-                        pw.print(" mAnimation="); pw.println(mAnimation);
-            }
-            if (mHasTransformation || mHasLocalTransformation) {
-                pw.print(prefix); pw.print("XForm: has=");
-                        pw.print(mHasTransformation);
-                        pw.print(" hasLocal="); pw.print(mHasLocalTransformation);
-                        pw.print(" "); mTransformation.printShortString(pw);
-                        pw.println();
-            }
-            if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) {
-                pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha);
-                        pw.print(" mAlpha="); pw.print(mAlpha);
-                        pw.print(" mLastAlpha="); pw.println(mLastAlpha);
-            }
-            if (mHaveMatrix) {
-                pw.print(prefix); pw.print("mDsDx="); pw.print(mDsDx);
-                        pw.print(" mDtDx="); pw.print(mDtDx);
-                        pw.print(" mDsDy="); pw.print(mDsDy);
-                        pw.print(" mDtDy="); pw.println(mDtDy);
-            }
-            pw.print(prefix); pw.print("mDrawPending="); pw.print(mDrawPending);
-                    pw.print(" mCommitDrawPending="); pw.print(mCommitDrawPending);
-                    pw.print(" mReadyToShow="); pw.print(mReadyToShow);
-                    pw.print(" mHasDrawn="); pw.println(mHasDrawn);
-            if (mExiting || mRemoveOnExit || mDestroying || mRemoved) {
-                pw.print(prefix); pw.print("mExiting="); pw.print(mExiting);
-                        pw.print(" mRemoveOnExit="); pw.print(mRemoveOnExit);
-                        pw.print(" mDestroying="); pw.print(mDestroying);
-                        pw.print(" mRemoved="); pw.println(mRemoved);
-            }
-            if (mOrientationChanging || mAppFreezing || mTurnOnScreen) {
-                pw.print(prefix); pw.print("mOrientationChanging=");
-                        pw.print(mOrientationChanging);
-                        pw.print(" mAppFreezing="); pw.print(mAppFreezing);
-                        pw.print(" mTurnOnScreen="); pw.println(mTurnOnScreen);
-            }
-            if (mHScale != 1 || mVScale != 1) {
-                pw.print(prefix); pw.print("mHScale="); pw.print(mHScale);
-                        pw.print(" mVScale="); pw.println(mVScale);
-            }
-            if (mWallpaperX != -1 || mWallpaperY != -1) {
-                pw.print(prefix); pw.print("mWallpaperX="); pw.print(mWallpaperX);
-                        pw.print(" mWallpaperY="); pw.println(mWallpaperY);
-            }
-            if (mWallpaperXStep != -1 || mWallpaperYStep != -1) {
-                pw.print(prefix); pw.print("mWallpaperXStep="); pw.print(mWallpaperXStep);
-                        pw.print(" mWallpaperYStep="); pw.println(mWallpaperYStep);
-            }
-        }
-        
-        String makeInputChannelName() {
-            return Integer.toHexString(System.identityHashCode(this))
-                + " " + mAttrs.getTitle();
-        }
-
-        @Override
-        public String toString() {
-            if (mStringNameCache == null || mLastTitle != mAttrs.getTitle()
-                    || mWasPaused != mToken.paused) {
-                mLastTitle = mAttrs.getTitle();
-                mWasPaused = mToken.paused;
-                mStringNameCache = "Window{" + Integer.toHexString(System.identityHashCode(this))
-                        + " " + mLastTitle + " paused=" + mWasPaused + "}";
-            }
-            return mStringNameCache;
-        }
-    }
-
-    // -------------------------------------------------------------
-    // Window Token State
-    // -------------------------------------------------------------
-
-    class WindowToken {
-        // The actual token.
-        final IBinder token;
-
-        // The type of window this token is for, as per WindowManager.LayoutParams.
-        final int windowType;
-
-        // Set if this token was explicitly added by a client, so should
-        // not be removed when all windows are removed.
-        final boolean explicit;
-
-        // For printing.
-        String stringName;
-
-        // If this is an AppWindowToken, this is non-null.
-        AppWindowToken appWindowToken;
-
-        // All of the windows associated with this token.
-        final ArrayList<WindowState> windows = new ArrayList<WindowState>();
-
-        // Is key dispatching paused for this token?
-        boolean paused = false;
-
-        // Should this token's windows be hidden?
-        boolean hidden;
-
-        // Temporary for finding which tokens no longer have visible windows.
-        boolean hasVisible;
-
-        // Set to true when this token is in a pending transaction where it
-        // will be shown.
-        boolean waitingToShow;
-
-        // Set to true when this token is in a pending transaction where it
-        // will be hidden.
-        boolean waitingToHide;
-
-        // Set to true when this token is in a pending transaction where its
-        // windows will be put to the bottom of the list.
-        boolean sendingToBottom;
-
-        // Set to true when this token is in a pending transaction where its
-        // windows will be put to the top of the list.
-        boolean sendingToTop;
-
-        WindowToken(IBinder _token, int type, boolean _explicit) {
-            token = _token;
-            windowType = type;
-            explicit = _explicit;
-        }
-
-        void dump(PrintWriter pw, String prefix) {
-            pw.print(prefix); pw.print("token="); pw.println(token);
-            pw.print(prefix); pw.print("windows="); pw.println(windows);
-            pw.print(prefix); pw.print("windowType="); pw.print(windowType);
-                    pw.print(" hidden="); pw.print(hidden);
-                    pw.print(" hasVisible="); pw.println(hasVisible);
-            if (waitingToShow || waitingToHide || sendingToBottom || sendingToTop) {
-                pw.print(prefix); pw.print("waitingToShow="); pw.print(waitingToShow);
-                        pw.print(" waitingToHide="); pw.print(waitingToHide);
-                        pw.print(" sendingToBottom="); pw.print(sendingToBottom);
-                        pw.print(" sendingToTop="); pw.println(sendingToTop);
-            }
-        }
-
-        @Override
-        public String toString() {
-            if (stringName == null) {
-                StringBuilder sb = new StringBuilder();
-                sb.append("WindowToken{");
-                sb.append(Integer.toHexString(System.identityHashCode(this)));
-                sb.append(" token="); sb.append(token); sb.append('}');
-                stringName = sb.toString();
-            }
-            return stringName;
-        }
-    };
-
-    class AppWindowToken extends WindowToken {
-        // Non-null only for application tokens.
-        final IApplicationToken appToken;
-
-        // All of the windows and child windows that are included in this
-        // application token.  Note this list is NOT sorted!
-        final ArrayList<WindowState> allAppWindows = new ArrayList<WindowState>();
-
-        int groupId = -1;
-        boolean appFullscreen;
-        int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
-        
-        // The input dispatching timeout for this application token in nanoseconds.
-        long inputDispatchingTimeoutNanos;
-
-        // These are used for determining when all windows associated with
-        // an activity have been drawn, so they can be made visible together
-        // at the same time.
-        int lastTransactionSequence = mTransactionSequence-1;
-        int numInterestingWindows;
-        int numDrawnWindows;
-        boolean inPendingTransaction;
-        boolean allDrawn;
-
-        // Is this token going to be hidden in a little while?  If so, it
-        // won't be taken into account for setting the screen orientation.
-        boolean willBeHidden;
-
-        // Is this window's surface needed?  This is almost like hidden, except
-        // it will sometimes be true a little earlier: when the token has
-        // been shown, but is still waiting for its app transition to execute
-        // before making its windows shown.
-        boolean hiddenRequested;
-
-        // Have we told the window clients to hide themselves?
-        boolean clientHidden;
-
-        // Last visibility state we reported to the app token.
-        boolean reportedVisible;
-
-        // Set to true when the token has been removed from the window mgr.
-        boolean removed;
-
-        // Have we been asked to have this token keep the screen frozen?
-        boolean freezingScreen;
-
-        boolean animating;
-        Animation animation;
-        boolean hasTransformation;
-        final Transformation transformation = new Transformation();
-
-        // Offset to the window of all layers in the token, for use by
-        // AppWindowToken animations.
-        int animLayerAdjustment;
-
-        // Information about an application starting window if displayed.
-        StartingData startingData;
-        WindowState startingWindow;
-        View startingView;
-        boolean startingDisplayed;
-        boolean startingMoved;
-        boolean firstWindowDrawn;
-
-        // Input application handle used by the input dispatcher.
-        InputApplicationHandle mInputApplicationHandle;
-
-        AppWindowToken(IApplicationToken _token) {
-            super(_token.asBinder(),
-                    WindowManager.LayoutParams.TYPE_APPLICATION, true);
-            appWindowToken = this;
-            appToken = _token;
-            mInputApplicationHandle = new InputApplicationHandle(this);
-        }
-
-        public void setAnimation(Animation anim) {
-            if (localLOGV) Slog.v(
-                TAG, "Setting animation in " + this + ": " + anim);
-            animation = anim;
-            animating = false;
-            anim.restrictDuration(MAX_ANIMATION_DURATION);
-            anim.scaleCurrentDuration(mTransitionAnimationScale);
-            int zorder = anim.getZAdjustment();
-            int adj = 0;
-            if (zorder == Animation.ZORDER_TOP) {
-                adj = TYPE_LAYER_OFFSET;
-            } else if (zorder == Animation.ZORDER_BOTTOM) {
-                adj = -TYPE_LAYER_OFFSET;
-            }
-
-            if (animLayerAdjustment != adj) {
-                animLayerAdjustment = adj;
-                updateLayers();
-            }
-        }
-
-        public void setDummyAnimation() {
-            if (animation == null) {
-                if (localLOGV) Slog.v(
-                    TAG, "Setting dummy animation in " + this);
-                animation = sDummyAnimation;
-            }
-        }
-
-        public void clearAnimation() {
-            if (animation != null) {
-                animation = null;
-                animating = true;
-            }
-        }
-
-        void updateLayers() {
-            final int N = allAppWindows.size();
-            final int adj = animLayerAdjustment;
-            for (int i=0; i<N; i++) {
-                WindowState w = allAppWindows.get(i);
-                w.mAnimLayer = w.mLayer + adj;
-                if (DEBUG_LAYERS) Slog.v(TAG, "Updating layer " + w + ": "
-                        + w.mAnimLayer);
-                if (w == mInputMethodTarget && !mInputMethodTargetWaitingAnim) {
-                    setInputMethodAnimLayerAdjustment(adj);
-                }
-                if (w == mWallpaperTarget && mLowerWallpaperTarget == null) {
-                    setWallpaperAnimLayerAdjustmentLocked(adj);
-                }
-            }
-        }
-
-        void sendAppVisibilityToClients() {
-            final int N = allAppWindows.size();
-            for (int i=0; i<N; i++) {
-                WindowState win = allAppWindows.get(i);
-                if (win == startingWindow && clientHidden) {
-                    // Don't hide the starting window.
-                    continue;
-                }
-                try {
-                    if (DEBUG_VISIBILITY) Slog.v(TAG,
-                            "Setting visibility of " + win + ": " + (!clientHidden));
-                    win.mClient.dispatchAppVisibility(!clientHidden);
-                } catch (RemoteException e) {
-                }
-            }
-        }
-
-        void showAllWindowsLocked() {
-            final int NW = allAppWindows.size();
-            for (int i=0; i<NW; i++) {
-                WindowState w = allAppWindows.get(i);
-                if (DEBUG_VISIBILITY) Slog.v(TAG,
-                        "performing show on: " + w);
-                w.performShowLocked();
-            }
-        }
-
-        // This must be called while inside a transaction.
-        boolean stepAnimationLocked(long currentTime, int dw, int dh) {
-            if (!mDisplayFrozen && mPolicy.isScreenOn()) {
-                // We will run animations as long as the display isn't frozen.
-
-                if (animation == sDummyAnimation) {
-                    // This guy is going to animate, but not yet.  For now count
-                    // it as not animating for purposes of scheduling transactions;
-                    // when it is really time to animate, this will be set to
-                    // a real animation and the next call will execute normally.
-                    return false;
-                }
-
-                if ((allDrawn || animating || startingDisplayed) && animation != null) {
-                    if (!animating) {
-                        if (DEBUG_ANIM) Slog.v(
-                            TAG, "Starting animation in " + this +
-                            " @ " + currentTime + ": dw=" + dw + " dh=" + dh
-                            + " scale=" + mTransitionAnimationScale
-                            + " allDrawn=" + allDrawn + " animating=" + animating);
-                        animation.initialize(dw, dh, dw, dh);
-                        animation.setStartTime(currentTime);
-                        animating = true;
-                    }
-                    transformation.clear();
-                    final boolean more = animation.getTransformation(
-                        currentTime, transformation);
-                    if (DEBUG_ANIM) Slog.v(
-                        TAG, "Stepped animation in " + this +
-                        ": more=" + more + ", xform=" + transformation);
-                    if (more) {
-                        // we're done!
-                        hasTransformation = true;
-                        return true;
-                    }
-                    if (DEBUG_ANIM) Slog.v(
-                        TAG, "Finished animation in " + this +
-                        " @ " + currentTime);
-                    animation = null;
-                }
-            } else if (animation != null) {
-                // If the display is frozen, and there is a pending animation,
-                // clear it and make sure we run the cleanup code.
-                animating = true;
-                animation = null;
-            }
-
-            hasTransformation = false;
-
-            if (!animating) {
-                return false;
-            }
-
-            clearAnimation();
-            animating = false;
-            if (animLayerAdjustment != 0) {
-                animLayerAdjustment = 0;
-                updateLayers();
-            }
-            if (mInputMethodTarget != null && mInputMethodTarget.mAppToken == this) {
-                moveInputMethodWindowsIfNeededLocked(true);
-            }
-
-            if (DEBUG_ANIM) Slog.v(
-                    TAG, "Animation done in " + this
-                    + ": reportedVisible=" + reportedVisible);
-
-            transformation.clear();
-
-            final int N = windows.size();
-            for (int i=0; i<N; i++) {
-                windows.get(i).finishExit();
-            }
-            updateReportedVisibilityLocked();
-
-            return false;
-        }
-
-        void updateReportedVisibilityLocked() {
-            if (appToken == null) {
-                return;
-            }
-
-            int numInteresting = 0;
-            int numVisible = 0;
-            boolean nowGone = true;
-
-            if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
-            final int N = allAppWindows.size();
-            for (int i=0; i<N; i++) {
-                WindowState win = allAppWindows.get(i);
-                if (win == startingWindow || win.mAppFreezing
-                        || win.mViewVisibility != View.VISIBLE
-                        || win.mAttrs.type == TYPE_APPLICATION_STARTING
-                        || win.mDestroying) {
-                    continue;
-                }
-                if (DEBUG_VISIBILITY) {
-                    Slog.v(TAG, "Win " + win + ": isDrawn="
-                            + win.isDrawnLw()
-                            + ", isAnimating=" + win.isAnimating());
-                    if (!win.isDrawnLw()) {
-                        Slog.v(TAG, "Not displayed: s=" + win.mSurface
-                                + " pv=" + win.mPolicyVisibility
-                                + " dp=" + win.mDrawPending
-                                + " cdp=" + win.mCommitDrawPending
-                                + " ah=" + win.mAttachedHidden
-                                + " th="
-                                + (win.mAppToken != null
-                                        ? win.mAppToken.hiddenRequested : false)
-                                + " a=" + win.mAnimating);
-                    }
-                }
-                numInteresting++;
-                if (win.isDrawnLw()) {
-                    if (!win.isAnimating()) {
-                        numVisible++;
-                    }
-                    nowGone = false;
-                } else if (win.isAnimating()) {
-                    nowGone = false;
-                }
-            }
-
-            boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting;
-            if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
-                    + numInteresting + " visible=" + numVisible);
-            if (nowVisible != reportedVisible) {
-                if (DEBUG_VISIBILITY) Slog.v(
-                        TAG, "Visibility changed in " + this
-                        + ": vis=" + nowVisible);
-                reportedVisible = nowVisible;
-                Message m = mH.obtainMessage(
-                        H.REPORT_APPLICATION_TOKEN_WINDOWS,
-                        nowVisible ? 1 : 0,
-                        nowGone ? 1 : 0,
-                        this);
-                    mH.sendMessage(m);
-            }
-        }
-
-        WindowState findMainWindow() {
-            int j = windows.size();
-            while (j > 0) {
-                j--;
-                WindowState win = windows.get(j);
-                if (win.mAttrs.type == WindowManager.LayoutParams.TYPE_BASE_APPLICATION
-                        || win.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
-                    return win;
-                }
-            }
-            return null;
-        }
-
-        void dump(PrintWriter pw, String prefix) {
-            super.dump(pw, prefix);
-            if (appToken != null) {
-                pw.print(prefix); pw.println("app=true");
-            }
-            if (allAppWindows.size() > 0) {
-                pw.print(prefix); pw.print("allAppWindows="); pw.println(allAppWindows);
-            }
-            pw.print(prefix); pw.print("groupId="); pw.print(groupId);
-                    pw.print(" appFullscreen="); pw.print(appFullscreen);
-                    pw.print(" requestedOrientation="); pw.println(requestedOrientation);
-            pw.print(prefix); pw.print("hiddenRequested="); pw.print(hiddenRequested);
-                    pw.print(" clientHidden="); pw.print(clientHidden);
-                    pw.print(" willBeHidden="); pw.print(willBeHidden);
-                    pw.print(" reportedVisible="); pw.println(reportedVisible);
-            if (paused || freezingScreen) {
-                pw.print(prefix); pw.print("paused="); pw.print(paused);
-                        pw.print(" freezingScreen="); pw.println(freezingScreen);
-            }
-            if (numInterestingWindows != 0 || numDrawnWindows != 0
-                    || inPendingTransaction || allDrawn) {
-                pw.print(prefix); pw.print("numInterestingWindows=");
-                        pw.print(numInterestingWindows);
-                        pw.print(" numDrawnWindows="); pw.print(numDrawnWindows);
-                        pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
-                        pw.print(" allDrawn="); pw.println(allDrawn);
-            }
-            if (animating || animation != null) {
-                pw.print(prefix); pw.print("animating="); pw.print(animating);
-                        pw.print(" animation="); pw.println(animation);
-            }
-            if (hasTransformation) {
-                pw.print(prefix); pw.print("XForm: ");
-                        transformation.printShortString(pw);
-                        pw.println();
-            }
-            if (animLayerAdjustment != 0) {
-                pw.print(prefix); pw.print("animLayerAdjustment="); pw.println(animLayerAdjustment);
-            }
-            if (startingData != null || removed || firstWindowDrawn) {
-                pw.print(prefix); pw.print("startingData="); pw.print(startingData);
-                        pw.print(" removed="); pw.print(removed);
-                        pw.print(" firstWindowDrawn="); pw.println(firstWindowDrawn);
-            }
-            if (startingWindow != null || startingView != null
-                    || startingDisplayed || startingMoved) {
-                pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
-                        pw.print(" startingView="); pw.print(startingView);
-                        pw.print(" startingDisplayed="); pw.print(startingDisplayed);
-                        pw.print(" startingMoved"); pw.println(startingMoved);
-            }
-        }
-
-        @Override
-        public String toString() {
-            if (stringName == null) {
-                StringBuilder sb = new StringBuilder();
-                sb.append("AppWindowToken{");
-                sb.append(Integer.toHexString(System.identityHashCode(this)));
-                sb.append(" token="); sb.append(token); sb.append('}');
-                stringName = sb.toString();
-            }
-            return stringName;
-        }
-    }
-
-    // -------------------------------------------------------------
-    // DummyAnimation
-    // -------------------------------------------------------------
-
     // This is an animation that does nothing: it just immediately finishes
     // itself every time it is called.  It is used as a stub animation in cases
     // where we want to synchronize multiple things that may be animating.
@@ -8919,26 +5826,7 @@
     // Async Handler
     // -------------------------------------------------------------
 
-    static final class StartingData {
-        final String pkg;
-        final int theme;
-        final CharSequence nonLocalizedLabel;
-        final int labelRes;
-        final int icon;
-        final int windowFlags;
-
-        StartingData(String _pkg, int _theme, CharSequence _nonLocalizedLabel,
-                int _labelRes, int _icon, int _windowFlags) {
-            pkg = _pkg;
-            theme = _theme;
-            nonLocalizedLabel = _nonLocalizedLabel;
-            labelRes = _labelRes;
-            icon = _icon;
-            windowFlags = _windowFlags;
-        }
-    }
-
-    private final class H extends Handler {
+    final class H extends Handler {
         public static final int REPORT_FOCUS_CHANGE = 2;
         public static final int REPORT_LOSING_FOCUS = 3;
         public static final int ANIMATE = 4;
@@ -9348,7 +6236,7 @@
             IInputContext inputContext) {
         if (client == null) throw new IllegalArgumentException("null client");
         if (inputContext == null) throw new IllegalArgumentException("null inputContext");
-        Session session = new Session(client, inputContext);
+        Session session = new Session(this, client, inputContext);
         return session;
     }
 
@@ -11482,148 +8370,6 @@
         return val;
     }
 
-    static class Watermark {
-        final String[] mTokens;
-        final String mText;
-        final Paint mTextPaint;
-        final int mTextWidth;
-        final int mTextHeight;
-        final int mTextAscent;
-        final int mTextDescent;
-        final int mDeltaX;
-        final int mDeltaY;
-
-        Surface mSurface;
-        int mLastDW;
-        int mLastDH;
-        boolean mDrawNeeded;
-
-        Watermark(Display display, SurfaceSession session, String[] tokens) {
-            final DisplayMetrics dm = new DisplayMetrics();
-            display.getMetrics(dm);
-
-            if (false) {
-                Log.i(TAG, "*********************** WATERMARK");
-                for (int i=0; i<tokens.length; i++) {
-                    Log.i(TAG, "  TOKEN #" + i + ": " + tokens[i]);
-                }
-            }
-
-            mTokens = tokens;
-
-            StringBuilder builder = new StringBuilder(32);
-            int len = mTokens[0].length();
-            len = len & ~1;
-            for (int i=0; i<len; i+=2) {
-                int c1 = mTokens[0].charAt(i);
-                int c2 = mTokens[0].charAt(i+1);
-                if (c1 >= 'a' && c1 <= 'f') c1 = c1 - 'a' + 10;
-                else if (c1 >= 'A' && c1 <= 'F') c1 = c1 - 'A' + 10;
-                else c1 -= '0';
-                if (c2 >= 'a' && c2 <= 'f') c2 = c2 - 'a' + 10;
-                else if (c2 >= 'A' && c2 <= 'F') c2 = c2 - 'A' + 10;
-                else c2 -= '0';
-                builder.append((char)(255-((c1*16)+c2)));
-            }
-            mText = builder.toString();
-            if (false) {
-                Log.i(TAG, "Final text: " + mText);
-            }
-
-            int fontSize = getPropertyInt(tokens, 1,
-                    TypedValue.COMPLEX_UNIT_DIP, 20, dm);
-
-            mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
-            mTextPaint.setTextSize(fontSize);
-            mTextPaint.setTypeface(Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD));
-
-            FontMetricsInt fm = mTextPaint.getFontMetricsInt();
-            mTextWidth = (int)mTextPaint.measureText(mText);
-            mTextAscent = fm.ascent;
-            mTextDescent = fm.descent;
-            mTextHeight = fm.descent - fm.ascent;
-
-            mDeltaX = getPropertyInt(tokens, 2,
-                    TypedValue.COMPLEX_UNIT_PX, mTextWidth*2, dm);
-            mDeltaY = getPropertyInt(tokens, 3,
-                    TypedValue.COMPLEX_UNIT_PX, mTextHeight*3, dm);
-            int shadowColor = getPropertyInt(tokens, 4,
-                    TypedValue.COMPLEX_UNIT_PX, 0xb0000000, dm);
-            int color = getPropertyInt(tokens, 5,
-                    TypedValue.COMPLEX_UNIT_PX, 0x60ffffff, dm);
-            int shadowRadius = getPropertyInt(tokens, 6,
-                    TypedValue.COMPLEX_UNIT_PX, 7, dm);
-            int shadowDx = getPropertyInt(tokens, 8,
-                    TypedValue.COMPLEX_UNIT_PX, 0, dm);
-            int shadowDy = getPropertyInt(tokens, 9,
-                    TypedValue.COMPLEX_UNIT_PX, 0, dm);
-
-            mTextPaint.setColor(color);
-            mTextPaint.setShadowLayer(shadowRadius, shadowDx, shadowDy, shadowColor);
-
-            try {
-                mSurface = new Surface(session, 0,
-                        "WatermarkSurface", -1, 1, 1, PixelFormat.TRANSLUCENT, 0);
-                mSurface.setLayer(TYPE_LAYER_MULTIPLIER*100);
-                mSurface.setPosition(0, 0);
-                mSurface.show();
-            } catch (OutOfResourcesException e) {
-            }
-        }
-
-        void positionSurface(int dw, int dh) {
-            if (mLastDW != dw || mLastDH != dh) {
-                mLastDW = dw;
-                mLastDH = dh;
-                mSurface.setSize(dw, dh);
-                mDrawNeeded = true;
-            }
-        }
-
-        void drawIfNeeded() {
-            if (mDrawNeeded) {
-                final int dw = mLastDW;
-                final int dh = mLastDH;
-
-                mDrawNeeded = false;
-                Rect dirty = new Rect(0, 0, dw, dh);
-                Canvas c = null;
-                try {
-                    c = mSurface.lockCanvas(dirty);
-                } catch (IllegalArgumentException e) {
-                } catch (OutOfResourcesException e) {
-                }
-                if (c != null) {
-                    c.drawColor(0, PorterDuff.Mode.CLEAR);
-                    
-                    int deltaX = mDeltaX;
-                    int deltaY = mDeltaY;
-
-                    // deltaX shouldn't be close to a round fraction of our
-                    // x step, or else things will line up too much.
-                    int div = (dw+mTextWidth)/deltaX;
-                    int rem = (dw+mTextWidth) - (div*deltaX);
-                    int qdelta = deltaX/4;
-                    if (rem < qdelta || rem > (deltaX-qdelta)) {
-                        deltaX += deltaX/3;
-                    }
-
-                    int y = -mTextHeight;
-                    int x = -mTextWidth;
-                    while (y < (dh+mTextHeight)) {
-                        c.drawText(mText, x, y, mTextPaint);
-                        x += deltaX;
-                        if (x >= dw) {
-                            x -= (dw+mTextWidth);
-                            y += deltaY;
-                        }
-                    }
-                    mSurface.unlockCanvasAndPost(c);
-                }
-            }
-        }
-    }
-
     void createWatermark() {
         if (mWatermark != null) {
             return;
@@ -11905,190 +8651,6 @@
         synchronized (mKeyguardTokenWatcher) { }
     }
 
-    /**
-     * DimAnimator class that controls the dim animation. This holds the surface and
-     * all state used for dim animation.
-     */
-    private static class DimAnimator {
-        Surface mDimSurface;
-        boolean mDimShown = false;
-        float mDimCurrentAlpha;
-        float mDimTargetAlpha;
-        float mDimDeltaPerMs;
-        long mLastDimAnimTime;
-        
-        int mLastDimWidth, mLastDimHeight;
-
-        DimAnimator (SurfaceSession session) {
-            if (mDimSurface == null) {
-                if (SHOW_TRANSACTIONS) Slog.i(TAG, "  DIM "
-                        + mDimSurface + ": CREATE");
-                try {
-                    mDimSurface = new Surface(session, 0,
-                            "DimSurface",
-                            -1, 16, 16, PixelFormat.OPAQUE,
-                            Surface.FX_SURFACE_DIM);
-                    mDimSurface.setAlpha(0.0f);
-                } catch (Exception e) {
-                    Slog.e(TAG, "Exception creating Dim surface", e);
-                }
-            }
-        }
-
-        /**
-         * Show the dim surface.
-         */
-        void show(int dw, int dh) {
-            if (!mDimShown) {
-                if (SHOW_TRANSACTIONS) Slog.i(TAG, "  DIM " + mDimSurface + ": SHOW pos=(0,0) (" +
-                        dw + "x" + dh + ")");
-                mDimShown = true;
-                try {
-                    mLastDimWidth = dw;
-                    mLastDimHeight = dh;
-                    mDimSurface.setPosition(0, 0);
-                    mDimSurface.setSize(dw, dh);
-                    mDimSurface.show();
-                } catch (RuntimeException e) {
-                    Slog.w(TAG, "Failure showing dim surface", e);
-                }
-            } else if (mLastDimWidth != dw || mLastDimHeight != dh) {
-                mLastDimWidth = dw;
-                mLastDimHeight = dh;
-                mDimSurface.setSize(dw, dh);
-            }
-        }
-
-        /**
-         * Set's the dim surface's layer and update dim parameters that will be used in
-         * {@link updateSurface} after all windows are examined.
-         */
-        void updateParameters(Resources res, WindowState w, long currentTime) {
-            mDimSurface.setLayer(w.mAnimLayer-1);
-
-            final float target = w.mExiting ? 0 : w.mAttrs.dimAmount;
-            if (SHOW_TRANSACTIONS) Slog.i(TAG, "  DIM " + mDimSurface
-                    + ": layer=" + (w.mAnimLayer-1) + " target=" + target);
-            if (mDimTargetAlpha != target) {
-                // If the desired dim level has changed, then
-                // start an animation to it.
-                mLastDimAnimTime = currentTime;
-                long duration = (w.mAnimating && w.mAnimation != null)
-                        ? w.mAnimation.computeDurationHint()
-                        : DEFAULT_DIM_DURATION;
-                if (target > mDimTargetAlpha) {
-                    TypedValue tv = new TypedValue();
-                    res.getValue(com.android.internal.R.fraction.config_dimBehindFadeDuration,
-                            tv, true);
-                    if (tv.type == TypedValue.TYPE_FRACTION) {
-                        duration = (long)tv.getFraction((float)duration, (float)duration);
-                    } else if (tv.type >= TypedValue.TYPE_FIRST_INT
-                            && tv.type <= TypedValue.TYPE_LAST_INT) {
-                        duration = tv.data;
-                    }
-                }
-                if (duration < 1) {
-                    // Don't divide by zero
-                    duration = 1;
-                }
-                mDimTargetAlpha = target;
-                mDimDeltaPerMs = (mDimTargetAlpha-mDimCurrentAlpha) / duration;
-            }
-        }
-
-        /**
-         * Updating the surface's alpha. Returns true if the animation continues, or returns
-         * false when the animation is finished and the dim surface is hidden.
-         */
-        boolean updateSurface(boolean dimming, long currentTime, boolean displayFrozen) {
-            if (!dimming) {
-                if (mDimTargetAlpha != 0) {
-                    mLastDimAnimTime = currentTime;
-                    mDimTargetAlpha = 0;
-                    mDimDeltaPerMs = (-mDimCurrentAlpha) / DEFAULT_DIM_DURATION;
-                }
-            }
-
-            boolean animating = false;
-            if (mLastDimAnimTime != 0) {
-                mDimCurrentAlpha += mDimDeltaPerMs
-                        * (currentTime-mLastDimAnimTime);
-                boolean more = true;
-                if (displayFrozen) {
-                    // If the display is frozen, there is no reason to animate.
-                    more = false;
-                } else if (mDimDeltaPerMs > 0) {
-                    if (mDimCurrentAlpha > mDimTargetAlpha) {
-                        more = false;
-                    }
-                } else if (mDimDeltaPerMs < 0) {
-                    if (mDimCurrentAlpha < mDimTargetAlpha) {
-                        more = false;
-                    }
-                } else {
-                    more = false;
-                }
-
-                // Do we need to continue animating?
-                if (more) {
-                    if (SHOW_TRANSACTIONS) Slog.i(TAG, "  DIM "
-                            + mDimSurface + ": alpha=" + mDimCurrentAlpha);
-                    mLastDimAnimTime = currentTime;
-                    mDimSurface.setAlpha(mDimCurrentAlpha);
-                    animating = true;
-                } else {
-                    mDimCurrentAlpha = mDimTargetAlpha;
-                    mLastDimAnimTime = 0;
-                    if (SHOW_TRANSACTIONS) Slog.i(TAG, "  DIM "
-                            + mDimSurface + ": final alpha=" + mDimCurrentAlpha);
-                    mDimSurface.setAlpha(mDimCurrentAlpha);
-                    if (!dimming) {
-                        if (SHOW_TRANSACTIONS) Slog.i(TAG, "  DIM " + mDimSurface
-                                + ": HIDE");
-                        try {
-                            mDimSurface.hide();
-                        } catch (RuntimeException e) {
-                            Slog.w(TAG, "Illegal argument exception hiding dim surface");
-                        }
-                        mDimShown = false;
-                    }
-                }
-            }
-            return animating;
-        }
-
-        public void printTo(PrintWriter pw) {
-            pw.print("  mDimShown="); pw.print(mDimShown);
-            pw.print(" current="); pw.print(mDimCurrentAlpha);
-            pw.print(" target="); pw.print(mDimTargetAlpha);
-            pw.print(" delta="); pw.print(mDimDeltaPerMs);
-            pw.print(" lastAnimTime="); pw.println(mLastDimAnimTime);
-        }
-    }
-
-    /**
-     * Animation that fade in after 0.5 interpolate time, or fade out in reverse order.
-     * This is used for opening/closing transition for apps in compatible mode.
-     */
-    private static class FadeInOutAnimation extends Animation {
-        boolean mFadeIn;
-
-        public FadeInOutAnimation(boolean fadeIn) {
-            setInterpolator(new AccelerateInterpolator());
-            setDuration(DEFAULT_FADE_IN_OUT_DURATION);
-            mFadeIn = fadeIn;
-        }
-
-        @Override
-        protected void applyTransformation(float interpolatedTime, Transformation t) {
-            float x = interpolatedTime;
-            if (!mFadeIn) {
-                x = 1.0f - x; // reverse the interpolation for fade out
-            }
-            t.setAlpha(x);
-        }
-    }
-
     public interface OnHardKeyboardStatusChangeListener {
         public void onHardKeyboardStatusChange(boolean available, boolean enabled);
     }
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
new file mode 100644
index 0000000..d0eec89
--- /dev/null
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -0,0 +1,1623 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
+import static android.view.WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
+import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
+import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
+
+import com.android.server.wm.WindowManagerService.H;
+
+import android.content.res.Configuration;
+import android.graphics.Matrix;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Slog;
+import android.view.Gravity;
+import android.view.IApplicationToken;
+import android.view.IWindow;
+import android.view.InputChannel;
+import android.view.Surface;
+import android.view.View;
+import android.view.ViewTreeObserver;
+import android.view.WindowManager;
+import android.view.WindowManagerPolicy;
+import android.view.WindowManager.LayoutParams;
+import android.view.animation.Animation;
+import android.view.animation.Transformation;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+/**
+ * A window in the window manager.
+ */
+final class WindowState implements WindowManagerPolicy.WindowState {
+    final WindowManagerService mService;
+    final Session mSession;
+    final IWindow mClient;
+    WindowToken mToken;
+    WindowToken mRootToken;
+    AppWindowToken mAppToken;
+    AppWindowToken mTargetAppToken;
+    final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams();
+    final DeathRecipient mDeathRecipient;
+    final WindowState mAttachedWindow;
+    final ArrayList<WindowState> mChildWindows = new ArrayList<WindowState>();
+    final int mBaseLayer;
+    final int mSubLayer;
+    final boolean mLayoutAttached;
+    final boolean mIsImWindow;
+    final boolean mIsWallpaper;
+    final boolean mIsFloatingLayer;
+    int mViewVisibility;
+    boolean mPolicyVisibility = true;
+    boolean mPolicyVisibilityAfterAnim = true;
+    boolean mAppFreezing;
+    Surface mSurface;
+    boolean mReportDestroySurface;
+    boolean mSurfacePendingDestroy;
+    boolean mAttachedHidden;    // is our parent window hidden?
+    boolean mLastHidden;        // was this window last hidden?
+    boolean mWallpaperVisible;  // for wallpaper, what was last vis report?
+    int mRequestedWidth;
+    int mRequestedHeight;
+    int mLastRequestedWidth;
+    int mLastRequestedHeight;
+    int mLayer;
+    int mAnimLayer;
+    int mLastLayer;
+    boolean mHaveFrame;
+    boolean mObscured;
+    boolean mTurnOnScreen;
+
+    int mLayoutSeq = -1;
+    
+    Configuration mConfiguration = null;
+    
+    // Actual frame shown on-screen (may be modified by animation)
+    final Rect mShownFrame = new Rect();
+    final Rect mLastShownFrame = new Rect();
+
+    /**
+     * Set when we have changed the size of the surface, to know that
+     * we must tell them application to resize (and thus redraw itself).
+     */
+    boolean mSurfaceResized;
+    
+    /**
+     * Insets that determine the actually visible area
+     */
+    final Rect mVisibleInsets = new Rect();
+    final Rect mLastVisibleInsets = new Rect();
+    boolean mVisibleInsetsChanged;
+
+    /**
+     * Insets that are covered by system windows
+     */
+    final Rect mContentInsets = new Rect();
+    final Rect mLastContentInsets = new Rect();
+    boolean mContentInsetsChanged;
+
+    /**
+     * Set to true if we are waiting for this window to receive its
+     * given internal insets before laying out other windows based on it.
+     */
+    boolean mGivenInsetsPending;
+
+    /**
+     * These are the content insets that were given during layout for
+     * this window, to be applied to windows behind it.
+     */
+    final Rect mGivenContentInsets = new Rect();
+
+    /**
+     * These are the visible insets that were given during layout for
+     * this window, to be applied to windows behind it.
+     */
+    final Rect mGivenVisibleInsets = new Rect();
+
+    /**
+     * This is the given touchable area relative to the window frame, or null if none.
+     */
+    final Region mGivenTouchableRegion = new Region();
+
+    /**
+     * Flag indicating whether the touchable region should be adjusted by
+     * the visible insets; if false the area outside the visible insets is
+     * NOT touchable, so we must use those to adjust the frame during hit
+     * tests.
+     */
+    int mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
+
+    // Current transformation being applied.
+    boolean mHaveMatrix;
+    float mDsDx=1, mDtDx=0, mDsDy=0, mDtDy=1;
+    float mLastDsDx=1, mLastDtDx=0, mLastDsDy=0, mLastDtDy=1;
+    float mHScale=1, mVScale=1;
+    float mLastHScale=1, mLastVScale=1;
+    final Matrix mTmpMatrix = new Matrix();
+
+    // "Real" frame that the application sees.
+    final Rect mFrame = new Rect();
+    final Rect mLastFrame = new Rect();
+
+    final Rect mContainingFrame = new Rect();
+    final Rect mDisplayFrame = new Rect();
+    final Rect mContentFrame = new Rect();
+    final Rect mParentFrame = new Rect();
+    final Rect mVisibleFrame = new Rect();
+
+    boolean mContentChanged;
+
+    float mShownAlpha = 1;
+    float mAlpha = 1;
+    float mLastAlpha = 1;
+
+    // Set to true if, when the window gets displayed, it should perform
+    // an enter animation.
+    boolean mEnterAnimationPending;
+
+    // Currently running animation.
+    boolean mAnimating;
+    boolean mLocalAnimating;
+    Animation mAnimation;
+    boolean mAnimationIsEntrance;
+    boolean mHasTransformation;
+    boolean mHasLocalTransformation;
+    final Transformation mTransformation = new Transformation();
+
+    // If a window showing a wallpaper: the requested offset for the
+    // wallpaper; if a wallpaper window: the currently applied offset.
+    float mWallpaperX = -1;
+    float mWallpaperY = -1;
+
+    // If a window showing a wallpaper: what fraction of the offset
+    // range corresponds to a full virtual screen.
+    float mWallpaperXStep = -1;
+    float mWallpaperYStep = -1;
+
+    // Wallpaper windows: pixels offset based on above variables.
+    int mXOffset;
+    int mYOffset;
+
+    // This is set after IWindowSession.relayout() has been called at
+    // least once for the window.  It allows us to detect the situation
+    // where we don't yet have a surface, but should have one soon, so
+    // we can give the window focus before waiting for the relayout.
+    boolean mRelayoutCalled;
+
+    // This is set after the Surface has been created but before the
+    // window has been drawn.  During this time the surface is hidden.
+    boolean mDrawPending;
+
+    // This is set after the window has finished drawing for the first
+    // time but before its surface is shown.  The surface will be
+    // displayed when the next layout is run.
+    boolean mCommitDrawPending;
+
+    // This is set during the time after the window's drawing has been
+    // committed, and before its surface is actually shown.  It is used
+    // to delay showing the surface until all windows in a token are ready
+    // to be shown.
+    boolean mReadyToShow;
+
+    // Set when the window has been shown in the screen the first time.
+    boolean mHasDrawn;
+
+    // Currently running an exit animation?
+    boolean mExiting;
+
+    // Currently on the mDestroySurface list?
+    boolean mDestroying;
+
+    // Completely remove from window manager after exit animation?
+    boolean mRemoveOnExit;
+
+    // Set when the orientation is changing and this window has not yet
+    // been updated for the new orientation.
+    boolean mOrientationChanging;
+
+    // Is this window now (or just being) removed?
+    boolean mRemoved;
+
+    // Temp for keeping track of windows that have been removed when
+    // rebuilding window list.
+    boolean mRebuilding;
+
+    // For debugging, this is the last information given to the surface flinger.
+    boolean mSurfaceShown;
+    int mSurfaceX, mSurfaceY, mSurfaceW, mSurfaceH;
+    int mSurfaceLayer;
+    float mSurfaceAlpha;
+    
+    // Input channel and input window handle used by the input dispatcher.
+    InputWindowHandle mInputWindowHandle;
+    InputChannel mInputChannel;
+    
+    // Used to improve performance of toString()
+    String mStringNameCache;
+    CharSequence mLastTitle;
+    boolean mWasPaused;
+
+    WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
+           WindowState attachedWindow, WindowManager.LayoutParams a,
+           int viewVisibility) {
+        mService = service;
+        mSession = s;
+        mClient = c;
+        mToken = token;
+        mAttrs.copyFrom(a);
+        mViewVisibility = viewVisibility;
+        DeathRecipient deathRecipient = new DeathRecipient();
+        mAlpha = a.alpha;
+        if (WindowManagerService.localLOGV) Slog.v(
+            WindowManagerService.TAG, "Window " + this + " client=" + c.asBinder()
+            + " token=" + token + " (" + mAttrs.token + ")");
+        try {
+            c.asBinder().linkToDeath(deathRecipient, 0);
+        } catch (RemoteException e) {
+            mDeathRecipient = null;
+            mAttachedWindow = null;
+            mLayoutAttached = false;
+            mIsImWindow = false;
+            mIsWallpaper = false;
+            mIsFloatingLayer = false;
+            mBaseLayer = 0;
+            mSubLayer = 0;
+            return;
+        }
+        mDeathRecipient = deathRecipient;
+
+        if ((mAttrs.type >= FIRST_SUB_WINDOW &&
+                mAttrs.type <= LAST_SUB_WINDOW)) {
+            // The multiplier here is to reserve space for multiple
+            // windows in the same type layer.
+            mBaseLayer = mService.mPolicy.windowTypeToLayerLw(
+                    attachedWindow.mAttrs.type) * WindowManagerService.TYPE_LAYER_MULTIPLIER
+                    + WindowManagerService.TYPE_LAYER_OFFSET;
+            mSubLayer = mService.mPolicy.subWindowTypeToLayerLw(a.type);
+            mAttachedWindow = attachedWindow;
+            if (WindowManagerService.DEBUG_ADD_REMOVE) Slog.v(WindowManagerService.TAG, "Adding " + this + " to " + mAttachedWindow);
+            mAttachedWindow.mChildWindows.add(this);
+            mLayoutAttached = mAttrs.type !=
+                    WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
+            mIsImWindow = attachedWindow.mAttrs.type == TYPE_INPUT_METHOD
+                    || attachedWindow.mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
+            mIsWallpaper = attachedWindow.mAttrs.type == TYPE_WALLPAPER;
+            mIsFloatingLayer = mIsImWindow || mIsWallpaper;
+        } else {
+            // The multiplier here is to reserve space for multiple
+            // windows in the same type layer.
+            mBaseLayer = mService.mPolicy.windowTypeToLayerLw(a.type)
+                    * WindowManagerService.TYPE_LAYER_MULTIPLIER
+                    + WindowManagerService.TYPE_LAYER_OFFSET;
+            mSubLayer = 0;
+            mAttachedWindow = null;
+            mLayoutAttached = false;
+            mIsImWindow = mAttrs.type == TYPE_INPUT_METHOD
+                    || mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
+            mIsWallpaper = mAttrs.type == TYPE_WALLPAPER;
+            mIsFloatingLayer = mIsImWindow || mIsWallpaper;
+        }
+
+        WindowState appWin = this;
+        while (appWin.mAttachedWindow != null) {
+            appWin = mAttachedWindow;
+        }
+        WindowToken appToken = appWin.mToken;
+        while (appToken.appWindowToken == null) {
+            WindowToken parent = mService.mTokenMap.get(appToken.token);
+            if (parent == null || appToken == parent) {
+                break;
+            }
+            appToken = parent;
+        }
+        mRootToken = appToken;
+        mAppToken = appToken.appWindowToken;
+
+        mSurface = null;
+        mRequestedWidth = 0;
+        mRequestedHeight = 0;
+        mLastRequestedWidth = 0;
+        mLastRequestedHeight = 0;
+        mXOffset = 0;
+        mYOffset = 0;
+        mLayer = 0;
+        mAnimLayer = 0;
+        mLastLayer = 0;
+        mInputWindowHandle = new InputWindowHandle(
+                mAppToken != null ? mAppToken.mInputApplicationHandle : null, this);
+    }
+
+    void attach() {
+        if (WindowManagerService.localLOGV) Slog.v(
+            WindowManagerService.TAG, "Attaching " + this + " token=" + mToken
+            + ", list=" + mToken.windows);
+        mSession.windowAddedLocked();
+    }
+
+    public void computeFrameLw(Rect pf, Rect df, Rect cf, Rect vf) {
+        mHaveFrame = true;
+
+        final Rect container = mContainingFrame;
+        container.set(pf);
+
+        final Rect display = mDisplayFrame;
+        display.set(df);
+
+        if ((mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
+            container.intersect(mService.mCompatibleScreenFrame);
+            if ((mAttrs.flags & FLAG_LAYOUT_NO_LIMITS) == 0) {
+                display.intersect(mService.mCompatibleScreenFrame);
+            }
+        }
+
+        final int pw = container.right - container.left;
+        final int ph = container.bottom - container.top;
+
+        int w,h;
+        if ((mAttrs.flags & mAttrs.FLAG_SCALED) != 0) {
+            w = mAttrs.width < 0 ? pw : mAttrs.width;
+            h = mAttrs.height< 0 ? ph : mAttrs.height;
+        } else {
+            w = mAttrs.width == mAttrs.MATCH_PARENT ? pw : mRequestedWidth;
+            h = mAttrs.height== mAttrs.MATCH_PARENT ? ph : mRequestedHeight;
+        }
+
+        if (!mParentFrame.equals(pf)) {
+            //Slog.i(TAG, "Window " + this + " content frame from " + mParentFrame
+            //        + " to " + pf);
+            mParentFrame.set(pf);
+            mContentChanged = true;
+        }
+
+        final Rect content = mContentFrame;
+        content.set(cf);
+
+        final Rect visible = mVisibleFrame;
+        visible.set(vf);
+
+        final Rect frame = mFrame;
+        final int fw = frame.width();
+        final int fh = frame.height();
+
+        //System.out.println("In: w=" + w + " h=" + h + " container=" +
+        //                   container + " x=" + mAttrs.x + " y=" + mAttrs.y);
+
+        Gravity.apply(mAttrs.gravity, w, h, container,
+                (int) (mAttrs.x + mAttrs.horizontalMargin * pw),
+                (int) (mAttrs.y + mAttrs.verticalMargin * ph), frame);
+
+        //System.out.println("Out: " + mFrame);
+
+        // Now make sure the window fits in the overall display.
+        Gravity.applyDisplay(mAttrs.gravity, df, frame);
+
+        // Make sure the content and visible frames are inside of the
+        // final window frame.
+        if (content.left < frame.left) content.left = frame.left;
+        if (content.top < frame.top) content.top = frame.top;
+        if (content.right > frame.right) content.right = frame.right;
+        if (content.bottom > frame.bottom) content.bottom = frame.bottom;
+        if (visible.left < frame.left) visible.left = frame.left;
+        if (visible.top < frame.top) visible.top = frame.top;
+        if (visible.right > frame.right) visible.right = frame.right;
+        if (visible.bottom > frame.bottom) visible.bottom = frame.bottom;
+
+        final Rect contentInsets = mContentInsets;
+        contentInsets.left = content.left-frame.left;
+        contentInsets.top = content.top-frame.top;
+        contentInsets.right = frame.right-content.right;
+        contentInsets.bottom = frame.bottom-content.bottom;
+
+        final Rect visibleInsets = mVisibleInsets;
+        visibleInsets.left = visible.left-frame.left;
+        visibleInsets.top = visible.top-frame.top;
+        visibleInsets.right = frame.right-visible.right;
+        visibleInsets.bottom = frame.bottom-visible.bottom;
+
+        if (mIsWallpaper && (fw != frame.width() || fh != frame.height())) {
+            mService.updateWallpaperOffsetLocked(this, mService.mDisplay.getWidth(),
+                    mService.mDisplay.getHeight(), false);
+        }
+
+        if (WindowManagerService.localLOGV) {
+            //if ("com.google.android.youtube".equals(mAttrs.packageName)
+            //        && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
+                Slog.v(WindowManagerService.TAG, "Resolving (mRequestedWidth="
+                        + mRequestedWidth + ", mRequestedheight="
+                        + mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph
+                        + "): frame=" + mFrame.toShortString()
+                        + " ci=" + contentInsets.toShortString()
+                        + " vi=" + visibleInsets.toShortString());
+            //}
+        }
+    }
+
+    public Rect getFrameLw() {
+        return mFrame;
+    }
+
+    public Rect getShownFrameLw() {
+        return mShownFrame;
+    }
+
+    public Rect getDisplayFrameLw() {
+        return mDisplayFrame;
+    }
+
+    public Rect getContentFrameLw() {
+        return mContentFrame;
+    }
+
+    public Rect getVisibleFrameLw() {
+        return mVisibleFrame;
+    }
+
+    public boolean getGivenInsetsPendingLw() {
+        return mGivenInsetsPending;
+    }
+
+    public Rect getGivenContentInsetsLw() {
+        return mGivenContentInsets;
+    }
+
+    public Rect getGivenVisibleInsetsLw() {
+        return mGivenVisibleInsets;
+    }
+
+    public WindowManager.LayoutParams getAttrs() {
+        return mAttrs;
+    }
+
+    public int getSurfaceLayer() {
+        return mLayer;
+    }
+
+    public IApplicationToken getAppToken() {
+        return mAppToken != null ? mAppToken.appToken : null;
+    }
+    
+    public long getInputDispatchingTimeoutNanos() {
+        return mAppToken != null
+                ? mAppToken.inputDispatchingTimeoutNanos
+                : WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
+    }
+
+    public boolean hasAppShownWindows() {
+        return mAppToken != null ? mAppToken.firstWindowDrawn : false;
+    }
+
+    public void setAnimation(Animation anim) {
+        if (WindowManagerService.localLOGV) Slog.v(
+            WindowManagerService.TAG, "Setting animation in " + this + ": " + anim);
+        mAnimating = false;
+        mLocalAnimating = false;
+        mAnimation = anim;
+        mAnimation.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION);
+        mAnimation.scaleCurrentDuration(mService.mWindowAnimationScale);
+    }
+
+    public void clearAnimation() {
+        if (mAnimation != null) {
+            mAnimating = true;
+            mLocalAnimating = false;
+            mAnimation.cancel();
+            mAnimation = null;
+        }
+    }
+
+    Surface createSurfaceLocked() {
+        if (mSurface == null) {
+            mReportDestroySurface = false;
+            mSurfacePendingDestroy = false;
+            mDrawPending = true;
+            mCommitDrawPending = false;
+            mReadyToShow = false;
+            if (mAppToken != null) {
+                mAppToken.allDrawn = false;
+            }
+
+            int flags = 0;
+
+            if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
+                flags |= Surface.SECURE;
+            }
+            if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(
+                WindowManagerService.TAG, "Creating surface in session "
+                + mSession.mSurfaceSession + " window " + this
+                + " w=" + mFrame.width()
+                + " h=" + mFrame.height() + " format="
+                + mAttrs.format + " flags=" + flags);
+
+            int w = mFrame.width();
+            int h = mFrame.height();
+            if ((mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) {
+                // for a scaled surface, we always want the requested
+                // size.
+                w = mRequestedWidth;
+                h = mRequestedHeight;
+            }
+
+            // Something is wrong and SurfaceFlinger will not like this,
+            // try to revert to sane values
+            if (w <= 0) w = 1;
+            if (h <= 0) h = 1;
+
+            mSurfaceShown = false;
+            mSurfaceLayer = 0;
+            mSurfaceAlpha = 1;
+            mSurfaceX = 0;
+            mSurfaceY = 0;
+            mSurfaceW = w;
+            mSurfaceH = h;
+            try {
+                final boolean isHwAccelerated = (mAttrs.flags &
+                        WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0;
+                final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : mAttrs.format;
+                if (isHwAccelerated && mAttrs.format == PixelFormat.OPAQUE) {
+                    flags |= Surface.OPAQUE;
+                }
+                mSurface = new Surface(
+                        mSession.mSurfaceSession, mSession.mPid,
+                        mAttrs.getTitle().toString(),
+                        0, w, h, format, flags);
+                if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "  CREATE SURFACE "
+                        + mSurface + " IN SESSION "
+                        + mSession.mSurfaceSession
+                        + ": pid=" + mSession.mPid + " format="
+                        + mAttrs.format + " flags=0x"
+                        + Integer.toHexString(flags)
+                        + " / " + this);
+            } catch (Surface.OutOfResourcesException e) {
+                Slog.w(WindowManagerService.TAG, "OutOfResourcesException creating surface");
+                mService.reclaimSomeSurfaceMemoryLocked(this, "create");
+                return null;
+            } catch (Exception e) {
+                Slog.e(WindowManagerService.TAG, "Exception creating surface", e);
+                return null;
+            }
+
+            if (WindowManagerService.localLOGV) Slog.v(
+                WindowManagerService.TAG, "Got surface: " + mSurface
+                + ", set left=" + mFrame.left + " top=" + mFrame.top
+                + ", animLayer=" + mAnimLayer);
+            if (WindowManagerService.SHOW_TRANSACTIONS) {
+                Slog.i(WindowManagerService.TAG, ">>> OPEN TRANSACTION createSurfaceLocked");
+                WindowManagerService.logSurface(this, "CREATE pos=(" + mFrame.left + "," + mFrame.top + ") (" +
+                        mFrame.width() + "x" + mFrame.height() + "), layer=" +
+                        mAnimLayer + " HIDE", null);
+            }
+            Surface.openTransaction();
+            try {
+                try {
+                    mSurfaceX = mFrame.left + mXOffset;
+                    mSurfaceY = mFrame.top + mYOffset;
+                    mSurface.setPosition(mSurfaceX, mSurfaceY);
+                    mSurfaceLayer = mAnimLayer;
+                    mSurface.setLayer(mAnimLayer);
+                    mSurfaceShown = false;
+                    mSurface.hide();
+                    if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_DITHER) != 0) {
+                        if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(this, "DITHER", null);
+                        mSurface.setFlags(Surface.SURFACE_DITHER,
+                                Surface.SURFACE_DITHER);
+                    }
+                } catch (RuntimeException e) {
+                    Slog.w(WindowManagerService.TAG, "Error creating surface in " + w, e);
+                    mService.reclaimSomeSurfaceMemoryLocked(this, "create-init");
+                }
+                mLastHidden = true;
+            } finally {
+                Surface.closeTransaction();
+                if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "<<< CLOSE TRANSACTION createSurfaceLocked");
+            }
+            if (WindowManagerService.localLOGV) Slog.v(
+                    WindowManagerService.TAG, "Created surface " + this);
+        }
+        return mSurface;
+    }
+
+    void destroySurfaceLocked() {
+        if (mAppToken != null && this == mAppToken.startingWindow) {
+            mAppToken.startingDisplayed = false;
+        }
+
+        if (mSurface != null) {
+            mDrawPending = false;
+            mCommitDrawPending = false;
+            mReadyToShow = false;
+
+            int i = mChildWindows.size();
+            while (i > 0) {
+                i--;
+                WindowState c = mChildWindows.get(i);
+                c.mAttachedHidden = true;
+            }
+
+            if (mReportDestroySurface) {
+                mReportDestroySurface = false;
+                mSurfacePendingDestroy = true;
+                try {
+                    mClient.dispatchGetNewSurface();
+                    // We'll really destroy on the next time around.
+                    return;
+                } catch (RemoteException e) {
+                }
+            }
+
+            try {
+                if (WindowManagerService.DEBUG_VISIBILITY) {
+                    RuntimeException e = null;
+                    if (!WindowManagerService.HIDE_STACK_CRAWLS) {
+                        e = new RuntimeException();
+                        e.fillInStackTrace();
+                    }
+                    Slog.w(WindowManagerService.TAG, "Window " + this + " destroying surface "
+                            + mSurface + ", session " + mSession, e);
+                }
+                if (WindowManagerService.SHOW_TRANSACTIONS) {
+                    RuntimeException e = null;
+                    if (!WindowManagerService.HIDE_STACK_CRAWLS) {
+                        e = new RuntimeException();
+                        e.fillInStackTrace();
+                    }
+                    if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(this, "DESTROY", e);
+                }
+                mSurface.destroy();
+            } catch (RuntimeException e) {
+                Slog.w(WindowManagerService.TAG, "Exception thrown when destroying Window " + this
+                    + " surface " + mSurface + " session " + mSession
+                    + ": " + e.toString());
+            }
+
+            mSurfaceShown = false;
+            mSurface = null;
+        }
+    }
+
+    boolean finishDrawingLocked() {
+        if (mDrawPending) {
+            if (WindowManagerService.SHOW_TRANSACTIONS || WindowManagerService.DEBUG_ORIENTATION) Slog.v(
+                WindowManagerService.TAG, "finishDrawingLocked: " + mSurface);
+            mCommitDrawPending = true;
+            mDrawPending = false;
+            return true;
+        }
+        return false;
+    }
+
+    // This must be called while inside a transaction.
+    boolean commitFinishDrawingLocked(long currentTime) {
+        //Slog.i(TAG, "commitFinishDrawingLocked: " + mSurface);
+        if (!mCommitDrawPending) {
+            return false;
+        }
+        mCommitDrawPending = false;
+        mReadyToShow = true;
+        final boolean starting = mAttrs.type == TYPE_APPLICATION_STARTING;
+        final AppWindowToken atoken = mAppToken;
+        if (atoken == null || atoken.allDrawn || starting) {
+            performShowLocked();
+        }
+        return true;
+    }
+
+    // This must be called while inside a transaction.
+    boolean performShowLocked() {
+        if (WindowManagerService.DEBUG_VISIBILITY) {
+            RuntimeException e = null;
+            if (!WindowManagerService.HIDE_STACK_CRAWLS) {
+                e = new RuntimeException();
+                e.fillInStackTrace();
+            }
+            Slog.v(WindowManagerService.TAG, "performShow on " + this
+                    + ": readyToShow=" + mReadyToShow + " readyForDisplay=" + isReadyForDisplay()
+                    + " starting=" + (mAttrs.type == TYPE_APPLICATION_STARTING), e);
+        }
+        if (mReadyToShow && isReadyForDisplay()) {
+            if (WindowManagerService.SHOW_TRANSACTIONS || WindowManagerService.DEBUG_ORIENTATION) WindowManagerService.logSurface(this,
+                    "SHOW (performShowLocked)", null);
+            if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "Showing " + this
+                    + " during animation: policyVis=" + mPolicyVisibility
+                    + " attHidden=" + mAttachedHidden
+                    + " tok.hiddenRequested="
+                    + (mAppToken != null ? mAppToken.hiddenRequested : false)
+                    + " tok.hidden="
+                    + (mAppToken != null ? mAppToken.hidden : false)
+                    + " animating=" + mAnimating
+                    + " tok animating="
+                    + (mAppToken != null ? mAppToken.animating : false));
+            if (!mService.showSurfaceRobustlyLocked(this)) {
+                return false;
+            }
+            mLastAlpha = -1;
+            mHasDrawn = true;
+            mLastHidden = false;
+            mReadyToShow = false;
+            mService.enableScreenIfNeededLocked();
+
+            mService.applyEnterAnimationLocked(this);
+
+            int i = mChildWindows.size();
+            while (i > 0) {
+                i--;
+                WindowState c = mChildWindows.get(i);
+                if (c.mAttachedHidden) {
+                    c.mAttachedHidden = false;
+                    if (c.mSurface != null) {
+                        c.performShowLocked();
+                        // It hadn't been shown, which means layout not
+                        // performed on it, so now we want to make sure to
+                        // do a layout.  If called from within the transaction
+                        // loop, this will cause it to restart with a new
+                        // layout.
+                        mService.mLayoutNeeded = true;
+                    }
+                }
+            }
+
+            if (mAttrs.type != TYPE_APPLICATION_STARTING
+                    && mAppToken != null) {
+                mAppToken.firstWindowDrawn = true;
+
+                if (mAppToken.startingData != null) {
+                    if (WindowManagerService.DEBUG_STARTING_WINDOW || WindowManagerService.DEBUG_ANIM) Slog.v(WindowManagerService.TAG,
+                            "Finish starting " + mToken
+                            + ": first real window is shown, no animation");
+                    // If this initial window is animating, stop it -- we
+                    // will do an animation to reveal it from behind the
+                    // starting window, so there is no need for it to also
+                    // be doing its own stuff.
+                    if (mAnimation != null) {
+                        mAnimation.cancel();
+                        mAnimation = null;
+                        // Make sure we clean up the animation.
+                        mAnimating = true;
+                    }
+                    mService.mFinishedStarting.add(mAppToken);
+                    mService.mH.sendEmptyMessage(H.FINISHED_STARTING);
+                }
+                mAppToken.updateReportedVisibilityLocked();
+            }
+        }
+        return true;
+    }
+
+    // This must be called while inside a transaction.  Returns true if
+    // there is more animation to run.
+    boolean stepAnimationLocked(long currentTime, int dw, int dh) {
+        if (!mService.mDisplayFrozen && mService.mPolicy.isScreenOn()) {
+            // We will run animations as long as the display isn't frozen.
+
+            if (!mDrawPending && !mCommitDrawPending && mAnimation != null) {
+                mHasTransformation = true;
+                mHasLocalTransformation = true;
+                if (!mLocalAnimating) {
+                    if (WindowManagerService.DEBUG_ANIM) Slog.v(
+                        WindowManagerService.TAG, "Starting animation in " + this +
+                        " @ " + currentTime + ": ww=" + mFrame.width() + " wh=" + mFrame.height() +
+                        " dw=" + dw + " dh=" + dh + " scale=" + mService.mWindowAnimationScale);
+                    mAnimation.initialize(mFrame.width(), mFrame.height(), dw, dh);
+                    mAnimation.setStartTime(currentTime);
+                    mLocalAnimating = true;
+                    mAnimating = true;
+                }
+                mTransformation.clear();
+                final boolean more = mAnimation.getTransformation(
+                    currentTime, mTransformation);
+                if (WindowManagerService.DEBUG_ANIM) Slog.v(
+                    WindowManagerService.TAG, "Stepped animation in " + this +
+                    ": more=" + more + ", xform=" + mTransformation);
+                if (more) {
+                    // we're not done!
+                    return true;
+                }
+                if (WindowManagerService.DEBUG_ANIM) Slog.v(
+                    WindowManagerService.TAG, "Finished animation in " + this +
+                    " @ " + currentTime);
+
+                if (mAnimation != null) {
+                    mAnimation.cancel();
+                    mAnimation = null;
+                }
+                //WindowManagerService.this.dump();
+            }
+            mHasLocalTransformation = false;
+            if ((!mLocalAnimating || mAnimationIsEntrance) && mAppToken != null
+                    && mAppToken.animation != null) {
+                // When our app token is animating, we kind-of pretend like
+                // we are as well.  Note the mLocalAnimating mAnimationIsEntrance
+                // part of this check means that we will only do this if
+                // our window is not currently exiting, or it is not
+                // locally animating itself.  The idea being that one that
+                // is exiting and doing a local animation should be removed
+                // once that animation is done.
+                mAnimating = true;
+                mHasTransformation = true;
+                mTransformation.clear();
+                return false;
+            } else if (mHasTransformation) {
+                // Little trick to get through the path below to act like
+                // we have finished an animation.
+                mAnimating = true;
+            } else if (isAnimating()) {
+                mAnimating = true;
+            }
+        } else if (mAnimation != null) {
+            // If the display is frozen, and there is a pending animation,
+            // clear it and make sure we run the cleanup code.
+            mAnimating = true;
+            mLocalAnimating = true;
+            mAnimation.cancel();
+            mAnimation = null;
+        }
+
+        if (!mAnimating && !mLocalAnimating) {
+            return false;
+        }
+
+        if (WindowManagerService.DEBUG_ANIM) Slog.v(
+            WindowManagerService.TAG, "Animation done in " + this + ": exiting=" + mExiting
+            + ", reportedVisible="
+            + (mAppToken != null ? mAppToken.reportedVisible : false));
+
+        mAnimating = false;
+        mLocalAnimating = false;
+        if (mAnimation != null) {
+            mAnimation.cancel();
+            mAnimation = null;
+        }
+        mAnimLayer = mLayer;
+        if (mIsImWindow) {
+            mAnimLayer += mService.mInputMethodAnimLayerAdjustment;
+        } else if (mIsWallpaper) {
+            mAnimLayer += mService.mWallpaperAnimLayerAdjustment;
+        }
+        if (WindowManagerService.DEBUG_LAYERS) Slog.v(WindowManagerService.TAG, "Stepping win " + this
+                + " anim layer: " + mAnimLayer);
+        mHasTransformation = false;
+        mHasLocalTransformation = false;
+        if (mPolicyVisibility != mPolicyVisibilityAfterAnim) {
+            if (WindowManagerService.DEBUG_VISIBILITY) {
+                Slog.v(WindowManagerService.TAG, "Policy visibility changing after anim in " + this + ": "
+                        + mPolicyVisibilityAfterAnim);
+            }
+            mPolicyVisibility = mPolicyVisibilityAfterAnim;
+            if (!mPolicyVisibility) {
+                if (mService.mCurrentFocus == this) {
+                    mService.mFocusMayChange = true;
+                }
+                // Window is no longer visible -- make sure if we were waiting
+                // for it to be displayed before enabling the display, that
+                // we allow the display to be enabled now.
+                mService.enableScreenIfNeededLocked();
+            }
+        }
+        mTransformation.clear();
+        if (mHasDrawn
+                && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
+                && mAppToken != null
+                && mAppToken.firstWindowDrawn
+                && mAppToken.startingData != null) {
+            if (WindowManagerService.DEBUG_STARTING_WINDOW) Slog.v(WindowManagerService.TAG, "Finish starting "
+                    + mToken + ": first real window done animating");
+            mService.mFinishedStarting.add(mAppToken);
+            mService.mH.sendEmptyMessage(H.FINISHED_STARTING);
+        }
+
+        finishExit();
+
+        if (mAppToken != null) {
+            mAppToken.updateReportedVisibilityLocked();
+        }
+
+        return false;
+    }
+
+    void finishExit() {
+        if (WindowManagerService.DEBUG_ANIM) Slog.v(
+                WindowManagerService.TAG, "finishExit in " + this
+                + ": exiting=" + mExiting
+                + " remove=" + mRemoveOnExit
+                + " windowAnimating=" + isWindowAnimating());
+
+        final int N = mChildWindows.size();
+        for (int i=0; i<N; i++) {
+            mChildWindows.get(i).finishExit();
+        }
+
+        if (!mExiting) {
+            return;
+        }
+
+        if (isWindowAnimating()) {
+            return;
+        }
+
+        if (WindowManagerService.localLOGV) Slog.v(
+                WindowManagerService.TAG, "Exit animation finished in " + this
+                + ": remove=" + mRemoveOnExit);
+        if (mSurface != null) {
+            mService.mDestroySurface.add(this);
+            mDestroying = true;
+            if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(this, "HIDE (finishExit)", null);
+            mSurfaceShown = false;
+            try {
+                mSurface.hide();
+            } catch (RuntimeException e) {
+                Slog.w(WindowManagerService.TAG, "Error hiding surface in " + this, e);
+            }
+            mLastHidden = true;
+        }
+        mExiting = false;
+        if (mRemoveOnExit) {
+            mService.mPendingRemove.add(this);
+            mRemoveOnExit = false;
+        }
+    }
+
+    boolean isIdentityMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
+        if (dsdx < .99999f || dsdx > 1.00001f) return false;
+        if (dtdy < .99999f || dtdy > 1.00001f) return false;
+        if (dtdx < -.000001f || dtdx > .000001f) return false;
+        if (dsdy < -.000001f || dsdy > .000001f) return false;
+        return true;
+    }
+
+    void computeShownFrameLocked() {
+        final boolean selfTransformation = mHasLocalTransformation;
+        Transformation attachedTransformation =
+                (mAttachedWindow != null && mAttachedWindow.mHasLocalTransformation)
+                ? mAttachedWindow.mTransformation : null;
+        Transformation appTransformation =
+                (mAppToken != null && mAppToken.hasTransformation)
+                ? mAppToken.transformation : null;
+
+        // Wallpapers are animated based on the "real" window they
+        // are currently targeting.
+        if (mAttrs.type == TYPE_WALLPAPER && mService.mLowerWallpaperTarget == null
+                && mService.mWallpaperTarget != null) {
+            if (mService.mWallpaperTarget.mHasLocalTransformation &&
+                    mService.mWallpaperTarget.mAnimation != null &&
+                    !mService.mWallpaperTarget.mAnimation.getDetachWallpaper()) {
+                attachedTransformation = mService.mWallpaperTarget.mTransformation;
+                if (WindowManagerService.DEBUG_WALLPAPER && attachedTransformation != null) {
+                    Slog.v(WindowManagerService.TAG, "WP target attached xform: " + attachedTransformation);
+                }
+            }
+            if (mService.mWallpaperTarget.mAppToken != null &&
+                    mService.mWallpaperTarget.mAppToken.hasTransformation &&
+                    mService.mWallpaperTarget.mAppToken.animation != null &&
+                    !mService.mWallpaperTarget.mAppToken.animation.getDetachWallpaper()) {
+                appTransformation = mService.mWallpaperTarget.mAppToken.transformation;
+                if (WindowManagerService.DEBUG_WALLPAPER && appTransformation != null) {
+                    Slog.v(WindowManagerService.TAG, "WP target app xform: " + appTransformation);
+                }
+            }
+        }
+
+        final boolean screenAnimation = mService.mScreenRotationAnimation != null
+                && mService.mScreenRotationAnimation.isAnimating();
+        if (selfTransformation || attachedTransformation != null
+                || appTransformation != null || screenAnimation) {
+            // cache often used attributes locally
+            final Rect frame = mFrame;
+            final float tmpFloats[] = mService.mTmpFloats;
+            final Matrix tmpMatrix = mTmpMatrix;
+
+            // Compute the desired transformation.
+            tmpMatrix.setTranslate(0, 0);
+            if (selfTransformation) {
+                tmpMatrix.postConcat(mTransformation.getMatrix());
+            }
+            tmpMatrix.postTranslate(frame.left + mXOffset, frame.top + mYOffset);
+            if (attachedTransformation != null) {
+                tmpMatrix.postConcat(attachedTransformation.getMatrix());
+            }
+            if (appTransformation != null) {
+                tmpMatrix.postConcat(appTransformation.getMatrix());
+            }
+            if (screenAnimation) {
+                tmpMatrix.postConcat(
+                        mService.mScreenRotationAnimation.getEnterTransformation().getMatrix());
+            }
+
+            // "convert" it into SurfaceFlinger's format
+            // (a 2x2 matrix + an offset)
+            // Here we must not transform the position of the surface
+            // since it is already included in the transformation.
+            //Slog.i(TAG, "Transform: " + matrix);
+
+            mHaveMatrix = true;
+            tmpMatrix.getValues(tmpFloats);
+            mDsDx = tmpFloats[Matrix.MSCALE_X];
+            mDtDx = tmpFloats[Matrix.MSKEW_Y];
+            mDsDy = tmpFloats[Matrix.MSKEW_X];
+            mDtDy = tmpFloats[Matrix.MSCALE_Y];
+            int x = (int)tmpFloats[Matrix.MTRANS_X];
+            int y = (int)tmpFloats[Matrix.MTRANS_Y];
+            int w = frame.width();
+            int h = frame.height();
+            mShownFrame.set(x, y, x+w, y+h);
+
+            // Now set the alpha...  but because our current hardware
+            // can't do alpha transformation on a non-opaque surface,
+            // turn it off if we are running an animation that is also
+            // transforming since it is more important to have that
+            // animation be smooth.
+            mShownAlpha = mAlpha;
+            if (!mService.mLimitedAlphaCompositing
+                    || (!PixelFormat.formatHasAlpha(mAttrs.format)
+                    || (isIdentityMatrix(mDsDx, mDtDx, mDsDy, mDtDy)
+                            && x == frame.left && y == frame.top))) {
+                //Slog.i(TAG, "Applying alpha transform");
+                if (selfTransformation) {
+                    mShownAlpha *= mTransformation.getAlpha();
+                }
+                if (attachedTransformation != null) {
+                    mShownAlpha *= attachedTransformation.getAlpha();
+                }
+                if (appTransformation != null) {
+                    mShownAlpha *= appTransformation.getAlpha();
+                }
+                if (screenAnimation) {
+                    mShownAlpha *=
+                        mService.mScreenRotationAnimation.getEnterTransformation().getAlpha();
+                }
+            } else {
+                //Slog.i(TAG, "Not applying alpha transform");
+            }
+
+            if (WindowManagerService.localLOGV) Slog.v(
+                WindowManagerService.TAG, "Continuing animation in " + this +
+                ": " + mShownFrame +
+                ", alpha=" + mTransformation.getAlpha());
+            return;
+        }
+
+        mShownFrame.set(mFrame);
+        if (mXOffset != 0 || mYOffset != 0) {
+            mShownFrame.offset(mXOffset, mYOffset);
+        }
+        mShownAlpha = mAlpha;
+        mHaveMatrix = false;
+        mDsDx = 1;
+        mDtDx = 0;
+        mDsDy = 0;
+        mDtDy = 1;
+    }
+
+    /**
+     * Is this window visible?  It is not visible if there is no
+     * surface, or we are in the process of running an exit animation
+     * that will remove the surface, or its app token has been hidden.
+     */
+    public boolean isVisibleLw() {
+        final AppWindowToken atoken = mAppToken;
+        return mSurface != null && mPolicyVisibility && !mAttachedHidden
+                && (atoken == null || !atoken.hiddenRequested)
+                && !mExiting && !mDestroying;
+    }
+
+    /**
+     * Like {@link #isVisibleLw}, but also counts a window that is currently
+     * "hidden" behind the keyguard as visible.  This allows us to apply
+     * things like window flags that impact the keyguard.
+     * XXX I am starting to think we need to have ANOTHER visibility flag
+     * for this "hidden behind keyguard" state rather than overloading
+     * mPolicyVisibility.  Ungh.
+     */
+    public boolean isVisibleOrBehindKeyguardLw() {
+        final AppWindowToken atoken = mAppToken;
+        return mSurface != null && !mAttachedHidden
+                && (atoken == null ? mPolicyVisibility : !atoken.hiddenRequested)
+                && !mDrawPending && !mCommitDrawPending
+                && !mExiting && !mDestroying;
+    }
+
+    /**
+     * Is this window visible, ignoring its app token?  It is not visible
+     * if there is no surface, or we are in the process of running an exit animation
+     * that will remove the surface.
+     */
+    public boolean isWinVisibleLw() {
+        final AppWindowToken atoken = mAppToken;
+        return mSurface != null && mPolicyVisibility && !mAttachedHidden
+                && (atoken == null || !atoken.hiddenRequested || atoken.animating)
+                && !mExiting && !mDestroying;
+    }
+
+    /**
+     * The same as isVisible(), but follows the current hidden state of
+     * the associated app token, not the pending requested hidden state.
+     */
+    boolean isVisibleNow() {
+        return mSurface != null && mPolicyVisibility && !mAttachedHidden
+                && !mRootToken.hidden && !mExiting && !mDestroying;
+    }
+
+    /**
+     * Can this window possibly be a drag/drop target?  The test here is
+     * a combination of the above "visible now" with the check that the
+     * Input Manager uses when discarding windows from input consideration.
+     */
+    boolean isPotentialDragTarget() {
+        return isVisibleNow() && (mInputChannel != null) && !mRemoved;
+    }
+
+    /**
+     * Same as isVisible(), but we also count it as visible between the
+     * call to IWindowSession.add() and the first relayout().
+     */
+    boolean isVisibleOrAdding() {
+        final AppWindowToken atoken = mAppToken;
+        return ((mSurface != null && !mReportDestroySurface)
+                        || (!mRelayoutCalled && mViewVisibility == View.VISIBLE))
+                && mPolicyVisibility && !mAttachedHidden
+                && (atoken == null || !atoken.hiddenRequested)
+                && !mExiting && !mDestroying;
+    }
+
+    /**
+     * Is this window currently on-screen?  It is on-screen either if it
+     * is visible or it is currently running an animation before no longer
+     * being visible.
+     */
+    boolean isOnScreen() {
+        final AppWindowToken atoken = mAppToken;
+        if (atoken != null) {
+            return mSurface != null && mPolicyVisibility && !mDestroying
+                    && ((!mAttachedHidden && !atoken.hiddenRequested)
+                            || mAnimation != null || atoken.animation != null);
+        } else {
+            return mSurface != null && mPolicyVisibility && !mDestroying
+                    && (!mAttachedHidden || mAnimation != null);
+        }
+    }
+
+    /**
+     * Like isOnScreen(), but we don't return true if the window is part
+     * of a transition that has not yet been started.
+     */
+    boolean isReadyForDisplay() {
+        if (mRootToken.waitingToShow &&
+                mService.mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
+            return false;
+        }
+        final AppWindowToken atoken = mAppToken;
+        final boolean animating = atoken != null
+                ? (atoken.animation != null) : false;
+        return mSurface != null && mPolicyVisibility && !mDestroying
+                && ((!mAttachedHidden && mViewVisibility == View.VISIBLE
+                                && !mRootToken.hidden)
+                        || mAnimation != null || animating);
+    }
+
+    /** Is the window or its container currently animating? */
+    boolean isAnimating() {
+        final WindowState attached = mAttachedWindow;
+        final AppWindowToken atoken = mAppToken;
+        return mAnimation != null
+                || (attached != null && attached.mAnimation != null)
+                || (atoken != null &&
+                        (atoken.animation != null
+                                || atoken.inPendingTransaction));
+    }
+
+    /** Is this window currently animating? */
+    boolean isWindowAnimating() {
+        return mAnimation != null;
+    }
+
+    /**
+     * Like isOnScreen, but returns false if the surface hasn't yet
+     * been drawn.
+     */
+    public boolean isDisplayedLw() {
+        final AppWindowToken atoken = mAppToken;
+        return mSurface != null && mPolicyVisibility && !mDestroying
+            && !mDrawPending && !mCommitDrawPending
+            && ((!mAttachedHidden &&
+                    (atoken == null || !atoken.hiddenRequested))
+                    || mAnimating);
+    }
+
+    /**
+     * Returns true if the window has a surface that it has drawn a
+     * complete UI in to.
+     */
+    public boolean isDrawnLw() {
+        final AppWindowToken atoken = mAppToken;
+        return mSurface != null && !mDestroying
+            && !mDrawPending && !mCommitDrawPending;
+    }
+
+    /**
+     * Return true if the window is opaque and fully drawn.  This indicates
+     * it may obscure windows behind it.
+     */
+    boolean isOpaqueDrawn() {
+        return (mAttrs.format == PixelFormat.OPAQUE
+                        || mAttrs.type == TYPE_WALLPAPER)
+                && mSurface != null && mAnimation == null
+                && (mAppToken == null || mAppToken.animation == null)
+                && !mDrawPending && !mCommitDrawPending;
+    }
+
+    /**
+     * Return whether this window is wanting to have a translation
+     * animation applied to it for an in-progress move.  (Only makes
+     * sense to call from performLayoutAndPlaceSurfacesLockedInner().)
+     */
+    boolean shouldAnimateMove() {
+        return mContentChanged && !mExiting && !mLastHidden && !mService.mDisplayFrozen
+                && (mFrame.top != mLastFrame.top
+                        || mFrame.left != mLastFrame.left)
+                && (mAttachedWindow == null || !mAttachedWindow.shouldAnimateMove())
+                && mService.mPolicy.isScreenOn();
+    }
+
+    boolean needsBackgroundFiller(int screenWidth, int screenHeight) {
+        return
+             // only if the application is requesting compatible window
+             (mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0 &&
+             // only if it's visible
+             mHasDrawn && mViewVisibility == View.VISIBLE &&
+             // and only if the application fills the compatible screen
+             mFrame.left <= mService.mCompatibleScreenFrame.left &&
+             mFrame.top <= mService.mCompatibleScreenFrame.top &&
+             mFrame.right >= mService.mCompatibleScreenFrame.right &&
+             mFrame.bottom >= mService.mCompatibleScreenFrame.bottom;
+    }
+
+    boolean isFullscreen(int screenWidth, int screenHeight) {
+        return mFrame.left <= 0 && mFrame.top <= 0 &&
+                mFrame.right >= screenWidth && mFrame.bottom >= screenHeight;
+    }
+
+    void removeLocked() {
+        disposeInputChannel();
+        
+        if (mAttachedWindow != null) {
+            if (WindowManagerService.DEBUG_ADD_REMOVE) Slog.v(WindowManagerService.TAG, "Removing " + this + " from " + mAttachedWindow);
+            mAttachedWindow.mChildWindows.remove(this);
+        }
+        destroySurfaceLocked();
+        mSession.windowRemovedLocked();
+        try {
+            mClient.asBinder().unlinkToDeath(mDeathRecipient, 0);
+        } catch (RuntimeException e) {
+            // Ignore if it has already been removed (usually because
+            // we are doing this as part of processing a death note.)
+        }
+    }
+    
+    void disposeInputChannel() {
+        if (mInputChannel != null) {
+            mService.mInputManager.unregisterInputChannel(mInputChannel);
+            
+            mInputChannel.dispose();
+            mInputChannel = null;
+        }
+    }
+
+    private class DeathRecipient implements IBinder.DeathRecipient {
+        public void binderDied() {
+            try {
+                synchronized(mService.mWindowMap) {
+                    WindowState win = mService.windowForClientLocked(mSession, mClient, false);
+                    Slog.i(WindowManagerService.TAG, "WIN DEATH: " + win);
+                    if (win != null) {
+                        mService.removeWindowLocked(mSession, win);
+                    }
+                }
+            } catch (IllegalArgumentException ex) {
+                // This will happen if the window has already been
+                // removed.
+            }
+        }
+    }
+
+    /** Returns true if this window desires key events. */
+    public final boolean canReceiveKeys() {
+        return     isVisibleOrAdding()
+                && (mViewVisibility == View.VISIBLE)
+                && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0);
+    }
+
+    public boolean hasDrawnLw() {
+        return mHasDrawn;
+    }
+
+    public boolean showLw(boolean doAnimation) {
+        return showLw(doAnimation, true);
+    }
+
+    boolean showLw(boolean doAnimation, boolean requestAnim) {
+        if (mPolicyVisibility && mPolicyVisibilityAfterAnim) {
+            return false;
+        }
+        if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "Policy visibility true: " + this);
+        if (doAnimation) {
+            if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "doAnimation: mPolicyVisibility="
+                    + mPolicyVisibility + " mAnimation=" + mAnimation);
+            if (mService.mDisplayFrozen || !mService.mPolicy.isScreenOn()) {
+                doAnimation = false;
+            } else if (mPolicyVisibility && mAnimation == null) {
+                // Check for the case where we are currently visible and
+                // not animating; we do not want to do animation at such a
+                // point to become visible when we already are.
+                doAnimation = false;
+            }
+        }
+        mPolicyVisibility = true;
+        mPolicyVisibilityAfterAnim = true;
+        if (doAnimation) {
+            mService.applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_ENTER, true);
+        }
+        if (requestAnim) {
+            mService.requestAnimationLocked(0);
+        }
+        return true;
+    }
+
+    public boolean hideLw(boolean doAnimation) {
+        return hideLw(doAnimation, true);
+    }
+
+    boolean hideLw(boolean doAnimation, boolean requestAnim) {
+        if (doAnimation) {
+            if (mService.mDisplayFrozen || !mService.mPolicy.isScreenOn()) {
+                doAnimation = false;
+            }
+        }
+        boolean current = doAnimation ? mPolicyVisibilityAfterAnim
+                : mPolicyVisibility;
+        if (!current) {
+            return false;
+        }
+        if (doAnimation) {
+            mService.applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_EXIT, false);
+            if (mAnimation == null) {
+                doAnimation = false;
+            }
+        }
+        if (doAnimation) {
+            mPolicyVisibilityAfterAnim = false;
+        } else {
+            if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "Policy visibility false: " + this);
+            mPolicyVisibilityAfterAnim = false;
+            mPolicyVisibility = false;
+            // Window is no longer visible -- make sure if we were waiting
+            // for it to be displayed before enabling the display, that
+            // we allow the display to be enabled now.
+            mService.enableScreenIfNeededLocked();
+            if (mService.mCurrentFocus == this) {
+                mService.mFocusMayChange = true;
+            }
+        }
+        if (requestAnim) {
+            mService.requestAnimationLocked(0);
+        }
+        return true;
+    }
+
+    public void getTouchableRegion(Region outRegion) {
+        final Rect frame = mFrame;
+        switch (mTouchableInsets) {
+            default:
+            case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME:
+                outRegion.set(frame);
+                break;
+            case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT: {
+                final Rect inset = mGivenContentInsets;
+                outRegion.set(
+                        frame.left + inset.left, frame.top + inset.top,
+                        frame.right - inset.right, frame.bottom - inset.bottom);
+                break;
+            }
+            case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE: {
+                final Rect inset = mGivenVisibleInsets;
+                outRegion.set(
+                        frame.left + inset.left, frame.top + inset.top,
+                        frame.right - inset.right, frame.bottom - inset.bottom);
+                break;
+            }
+            case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION: {
+                final Region givenTouchableRegion = mGivenTouchableRegion;
+                outRegion.set(givenTouchableRegion);
+                outRegion.translate(frame.left, frame.top);
+                break;
+            }
+        }
+    }
+
+    void dump(PrintWriter pw, String prefix) {
+        pw.print(prefix); pw.print("mSession="); pw.print(mSession);
+                pw.print(" mClient="); pw.println(mClient.asBinder());
+        pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs);
+        if (mAttachedWindow != null || mLayoutAttached) {
+            pw.print(prefix); pw.print("mAttachedWindow="); pw.print(mAttachedWindow);
+                    pw.print(" mLayoutAttached="); pw.println(mLayoutAttached);
+        }
+        if (mIsImWindow || mIsWallpaper || mIsFloatingLayer) {
+            pw.print(prefix); pw.print("mIsImWindow="); pw.print(mIsImWindow);
+                    pw.print(" mIsWallpaper="); pw.print(mIsWallpaper);
+                    pw.print(" mIsFloatingLayer="); pw.print(mIsFloatingLayer);
+                    pw.print(" mWallpaperVisible="); pw.println(mWallpaperVisible);
+        }
+        pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer);
+                pw.print(" mSubLayer="); pw.print(mSubLayer);
+                pw.print(" mAnimLayer="); pw.print(mLayer); pw.print("+");
+                pw.print((mTargetAppToken != null ? mTargetAppToken.animLayerAdjustment
+                      : (mAppToken != null ? mAppToken.animLayerAdjustment : 0)));
+                pw.print("="); pw.print(mAnimLayer);
+                pw.print(" mLastLayer="); pw.println(mLastLayer);
+        if (mSurface != null) {
+            pw.print(prefix); pw.print("mSurface="); pw.println(mSurface);
+            pw.print(prefix); pw.print("Surface: shown="); pw.print(mSurfaceShown);
+                    pw.print(" layer="); pw.print(mSurfaceLayer);
+                    pw.print(" alpha="); pw.print(mSurfaceAlpha);
+                    pw.print(" rect=("); pw.print(mSurfaceX);
+                    pw.print(","); pw.print(mSurfaceY);
+                    pw.print(") "); pw.print(mSurfaceW);
+                    pw.print(" x "); pw.println(mSurfaceH);
+        }
+        pw.print(prefix); pw.print("mToken="); pw.println(mToken);
+        pw.print(prefix); pw.print("mRootToken="); pw.println(mRootToken);
+        if (mAppToken != null) {
+            pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken);
+        }
+        if (mTargetAppToken != null) {
+            pw.print(prefix); pw.print("mTargetAppToken="); pw.println(mTargetAppToken);
+        }
+        pw.print(prefix); pw.print("mViewVisibility=0x");
+                pw.print(Integer.toHexString(mViewVisibility));
+                pw.print(" mLastHidden="); pw.print(mLastHidden);
+                pw.print(" mHaveFrame="); pw.print(mHaveFrame);
+                pw.print(" mObscured="); pw.println(mObscured);
+        if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || mAttachedHidden) {
+            pw.print(prefix); pw.print("mPolicyVisibility=");
+                    pw.print(mPolicyVisibility);
+                    pw.print(" mPolicyVisibilityAfterAnim=");
+                    pw.print(mPolicyVisibilityAfterAnim);
+                    pw.print(" mAttachedHidden="); pw.println(mAttachedHidden);
+        }
+        if (!mRelayoutCalled) {
+            pw.print(prefix); pw.print("mRelayoutCalled="); pw.println(mRelayoutCalled);
+        }
+        pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth);
+                pw.print(" h="); pw.print(mRequestedHeight);
+                pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
+        if (mXOffset != 0 || mYOffset != 0) {
+            pw.print(prefix); pw.print("Offsets x="); pw.print(mXOffset);
+                    pw.print(" y="); pw.println(mYOffset);
+        }
+        pw.print(prefix); pw.print("mGivenContentInsets=");
+                mGivenContentInsets.printShortString(pw);
+                pw.print(" mGivenVisibleInsets=");
+                mGivenVisibleInsets.printShortString(pw);
+                pw.println();
+        if (mTouchableInsets != 0 || mGivenInsetsPending) {
+            pw.print(prefix); pw.print("mTouchableInsets="); pw.print(mTouchableInsets);
+                    pw.print(" mGivenInsetsPending="); pw.println(mGivenInsetsPending);
+        }
+        pw.print(prefix); pw.print("mConfiguration="); pw.println(mConfiguration);
+        pw.print(prefix); pw.print("mShownFrame=");
+                mShownFrame.printShortString(pw);
+                pw.print(" last="); mLastShownFrame.printShortString(pw);
+                pw.println();
+        pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw);
+                pw.print(" last="); mLastFrame.printShortString(pw);
+                pw.println();
+        pw.print(prefix); pw.print("mContainingFrame=");
+                mContainingFrame.printShortString(pw);
+                pw.print(" mParentFrame=");
+                mParentFrame.printShortString(pw);
+                pw.print(" mDisplayFrame=");
+                mDisplayFrame.printShortString(pw);
+                pw.println();
+        pw.print(prefix); pw.print("mContentFrame="); mContentFrame.printShortString(pw);
+                pw.print(" mVisibleFrame="); mVisibleFrame.printShortString(pw);
+                pw.println();
+        pw.print(prefix); pw.print("mContentInsets="); mContentInsets.printShortString(pw);
+                pw.print(" last="); mLastContentInsets.printShortString(pw);
+                pw.print(" mVisibleInsets="); mVisibleInsets.printShortString(pw);
+                pw.print(" last="); mLastVisibleInsets.printShortString(pw);
+                pw.println();
+        if (mAnimating || mLocalAnimating || mAnimationIsEntrance
+                || mAnimation != null) {
+            pw.print(prefix); pw.print("mAnimating="); pw.print(mAnimating);
+                    pw.print(" mLocalAnimating="); pw.print(mLocalAnimating);
+                    pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance);
+                    pw.print(" mAnimation="); pw.println(mAnimation);
+        }
+        if (mHasTransformation || mHasLocalTransformation) {
+            pw.print(prefix); pw.print("XForm: has=");
+                    pw.print(mHasTransformation);
+                    pw.print(" hasLocal="); pw.print(mHasLocalTransformation);
+                    pw.print(" "); mTransformation.printShortString(pw);
+                    pw.println();
+        }
+        if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) {
+            pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha);
+                    pw.print(" mAlpha="); pw.print(mAlpha);
+                    pw.print(" mLastAlpha="); pw.println(mLastAlpha);
+        }
+        if (mHaveMatrix) {
+            pw.print(prefix); pw.print("mDsDx="); pw.print(mDsDx);
+                    pw.print(" mDtDx="); pw.print(mDtDx);
+                    pw.print(" mDsDy="); pw.print(mDsDy);
+                    pw.print(" mDtDy="); pw.println(mDtDy);
+        }
+        pw.print(prefix); pw.print("mDrawPending="); pw.print(mDrawPending);
+                pw.print(" mCommitDrawPending="); pw.print(mCommitDrawPending);
+                pw.print(" mReadyToShow="); pw.print(mReadyToShow);
+                pw.print(" mHasDrawn="); pw.println(mHasDrawn);
+        if (mExiting || mRemoveOnExit || mDestroying || mRemoved) {
+            pw.print(prefix); pw.print("mExiting="); pw.print(mExiting);
+                    pw.print(" mRemoveOnExit="); pw.print(mRemoveOnExit);
+                    pw.print(" mDestroying="); pw.print(mDestroying);
+                    pw.print(" mRemoved="); pw.println(mRemoved);
+        }
+        if (mOrientationChanging || mAppFreezing || mTurnOnScreen) {
+            pw.print(prefix); pw.print("mOrientationChanging=");
+                    pw.print(mOrientationChanging);
+                    pw.print(" mAppFreezing="); pw.print(mAppFreezing);
+                    pw.print(" mTurnOnScreen="); pw.println(mTurnOnScreen);
+        }
+        if (mHScale != 1 || mVScale != 1) {
+            pw.print(prefix); pw.print("mHScale="); pw.print(mHScale);
+                    pw.print(" mVScale="); pw.println(mVScale);
+        }
+        if (mWallpaperX != -1 || mWallpaperY != -1) {
+            pw.print(prefix); pw.print("mWallpaperX="); pw.print(mWallpaperX);
+                    pw.print(" mWallpaperY="); pw.println(mWallpaperY);
+        }
+        if (mWallpaperXStep != -1 || mWallpaperYStep != -1) {
+            pw.print(prefix); pw.print("mWallpaperXStep="); pw.print(mWallpaperXStep);
+                    pw.print(" mWallpaperYStep="); pw.println(mWallpaperYStep);
+        }
+    }
+    
+    String makeInputChannelName() {
+        return Integer.toHexString(System.identityHashCode(this))
+            + " " + mAttrs.getTitle();
+    }
+
+    @Override
+    public String toString() {
+        if (mStringNameCache == null || mLastTitle != mAttrs.getTitle()
+                || mWasPaused != mToken.paused) {
+            mLastTitle = mAttrs.getTitle();
+            mWasPaused = mToken.paused;
+            mStringNameCache = "Window{" + Integer.toHexString(System.identityHashCode(this))
+                    + " " + mLastTitle + " paused=" + mWasPaused + "}";
+        }
+        return mStringNameCache;
+    }
+}
\ No newline at end of file
diff --git a/services/java/com/android/server/wm/WindowToken.java b/services/java/com/android/server/wm/WindowToken.java
new file mode 100644
index 0000000..3cd256e
--- /dev/null
+++ b/services/java/com/android/server/wm/WindowToken.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import android.os.IBinder;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+/**
+ * Container of a set of related windows in the window manager.  Often this
+ * is an AppWindowToken, which is the handle for an Activity that it uses
+ * to display windows.  For nested windows, there is a WindowToken created for
+ * the parent window to manage its children.
+ */
+class WindowToken {
+    // The window manager!
+    final WindowManagerService service;
+    
+    // The actual token.
+    final IBinder token;
+
+    // The type of window this token is for, as per WindowManager.LayoutParams.
+    final int windowType;
+
+    // Set if this token was explicitly added by a client, so should
+    // not be removed when all windows are removed.
+    final boolean explicit;
+
+    // For printing.
+    String stringName;
+
+    // If this is an AppWindowToken, this is non-null.
+    AppWindowToken appWindowToken;
+
+    // All of the windows associated with this token.
+    final ArrayList<WindowState> windows = new ArrayList<WindowState>();
+
+    // Is key dispatching paused for this token?
+    boolean paused = false;
+
+    // Should this token's windows be hidden?
+    boolean hidden;
+
+    // Temporary for finding which tokens no longer have visible windows.
+    boolean hasVisible;
+
+    // Set to true when this token is in a pending transaction where it
+    // will be shown.
+    boolean waitingToShow;
+
+    // Set to true when this token is in a pending transaction where it
+    // will be hidden.
+    boolean waitingToHide;
+
+    // Set to true when this token is in a pending transaction where its
+    // windows will be put to the bottom of the list.
+    boolean sendingToBottom;
+
+    // Set to true when this token is in a pending transaction where its
+    // windows will be put to the top of the list.
+    boolean sendingToTop;
+
+    WindowToken(WindowManagerService _service, IBinder _token, int type, boolean _explicit) {
+        service = _service;
+        token = _token;
+        windowType = type;
+        explicit = _explicit;
+    }
+
+    void dump(PrintWriter pw, String prefix) {
+        pw.print(prefix); pw.print("token="); pw.println(token);
+        pw.print(prefix); pw.print("windows="); pw.println(windows);
+        pw.print(prefix); pw.print("windowType="); pw.print(windowType);
+                pw.print(" hidden="); pw.print(hidden);
+                pw.print(" hasVisible="); pw.println(hasVisible);
+        if (waitingToShow || waitingToHide || sendingToBottom || sendingToTop) {
+            pw.print(prefix); pw.print("waitingToShow="); pw.print(waitingToShow);
+                    pw.print(" waitingToHide="); pw.print(waitingToHide);
+                    pw.print(" sendingToBottom="); pw.print(sendingToBottom);
+                    pw.print(" sendingToTop="); pw.println(sendingToTop);
+        }
+    }
+
+    @Override
+    public String toString() {
+        if (stringName == null) {
+            StringBuilder sb = new StringBuilder();
+            sb.append("WindowToken{");
+            sb.append(Integer.toHexString(System.identityHashCode(this)));
+            sb.append(" token="); sb.append(token); sb.append('}');
+            stringName = sb.toString();
+        }
+        return stringName;
+    }
+}
\ No newline at end of file