Switch to using ModelViewController-based CarouselView

Change-Id: I5cd2ff8ce9b2102ab6b10f6d6a41f87e0f3a06f3
diff --git a/carousel/java/com/android/ex/carousel/CarouselController.java b/carousel/java/com/android/ex/carousel/CarouselController.java
index 7631948..f28d3f5 100644
--- a/carousel/java/com/android/ex/carousel/CarouselController.java
+++ b/carousel/java/com/android/ex/carousel/CarouselController.java
@@ -17,7 +17,7 @@
 package com.android.ex.carousel;
 
 import com.android.ex.carousel.CarouselRS.CarouselCallback;
-import com.android.ex.carousel.MVCCarouselView.DetailAlignment;
+import com.android.ex.carousel.CarouselView.DetailAlignment;
 
 import android.content.res.Resources;
 import android.graphics.Bitmap;
@@ -103,6 +103,7 @@
         setVisibleDetails(mVisibleDetails);
         setPrefetchCardCount(mPrefetchCardCount);
         setDetailTextureAlignment(mDetailTextureAlignment);
+        setDrawCardsWithBlending(mDrawCardsWithBlending);
         setDrawRuler(mDrawRuler);
         setCallback(mCarouselCallback);
         setDefaultBitmap(mDefaultBitmap);
diff --git a/carousel/java/com/android/ex/carousel/CarouselView.java b/carousel/java/com/android/ex/carousel/CarouselView.java
index 0b6bc3f..2223bd1 100644
--- a/carousel/java/com/android/ex/carousel/CarouselView.java
+++ b/carousel/java/com/android/ex/carousel/CarouselView.java
@@ -44,15 +44,6 @@
  */
 public abstract class CarouselView extends RSSurfaceView {
     private static final boolean USE_DEPTH_BUFFER = true;
-    private final int DEFAULT_SLOT_COUNT = 10;
-    private final float DEFAULT_RADIUS = 20.0f;
-    private final int DEFAULT_VISIBLE_DETAIL_COUNT = 3;
-    private final int DEFAULT_PREFETCH_CARD_COUNT = 2;
-    private final float DEFAULT_SWAY_SENSITIVITY = 0.0f;
-    private final float DEFAULT_FRICTION_COEFFICIENT = 10.0f;
-    private final float DEFAULT_DRAG_FACTOR = 0.25f;
-    private final int DEFAULT_DETAIL_ALIGNMENT =
-            DetailAlignment.VIEW_TOP | DetailAlignment.LEFT;
     private static final String TAG = "CarouselView";
     private static final boolean DBG = false;
     private CarouselRS mRenderScript;
@@ -60,40 +51,7 @@
     private Context mContext;
     private boolean mTracking;
 
-    // These shadow the state of the renderer in case the surface changes so the surface
-    // can be restored to its previous state.
-    private Bitmap mDefaultBitmap;
-    private Bitmap mLoadingBitmap;
-    private Bitmap mBackgroundBitmap;
-    private Bitmap mDefaultLineBitmap = Bitmap.createBitmap(
-            new int[] {0x00000000, 0xffffffff, 0x00000000}, 0, 3, 3, 1, Bitmap.Config.ARGB_4444);
-    private Mesh mDefaultGeometry;
-    private Mesh mLoadingGeometry;
-    private int mCardCount = 0;
-    private int mVisibleSlots = 0;
-    private int mVisibleDetails = DEFAULT_VISIBLE_DETAIL_COUNT;
-    private int mPrefetchCardCount = DEFAULT_PREFETCH_CARD_COUNT;
-    private int mDetailTextureAlignment = DEFAULT_DETAIL_ALIGNMENT;
-    private boolean mDrawCardsWithBlending = true;
-    private boolean mDrawRuler = true;
-    private float mStartAngle;
-    private float mCarouselRotationAngle;
-    private float mRadius = DEFAULT_RADIUS;
-    private float mCardRotation = 0.0f;
-    private boolean mCardsFaceTangent = false;
-    private float mSwaySensitivity = DEFAULT_SWAY_SENSITIVITY;
-    private float mFrictionCoefficient = DEFAULT_FRICTION_COEFFICIENT;
-    private float mDragFactor = DEFAULT_DRAG_FACTOR;
-    private int mSlotCount = DEFAULT_SLOT_COUNT;
-    private float mEye[] = { 20.6829f, 2.77081f, 16.7314f };
-    private float mAt[] = { 14.7255f, -3.40001f, -1.30184f };
-    private float mUp[] = { 0.0f, 1.0f, 0.0f };
-    private Float4 mBackgroundColor = new Float4(0.0f, 0.0f, 0.0f, 1.0f);
-    private CarouselCallback mCarouselCallback;
-    private float mRezInCardCount = 0.0f;
-    private long mFadeInDuration = 250L;
-    private Bitmap mDetailLoadingBitmap = Bitmap.createBitmap(
-            new int[] {0}, 0, 1, 1, 1, Bitmap.Config.ARGB_4444);
+    CarouselController mController;
 
     // Note: remember to update carousel.rs when changing the values below
     public static class DetailAlignment {
@@ -138,23 +96,32 @@
     public abstract Info getRenderScriptInfo();
 
     public CarouselView(Context context) {
-        this(context, null);
+        this(context, new CarouselController());
+    }
+
+    public CarouselView(Context context, CarouselController controller) {
+        this(context, null, controller);
     }
 
     /**
      * Constructor used when this widget is created from a layout file.
      */
     public CarouselView(Context context, AttributeSet attrs) {
+        this(context, attrs, new CarouselController());
+    }
+
+    public CarouselView(Context context, AttributeSet attrs, CarouselController controller) {
         super(context, attrs);
         mContext = context;
+        mController = controller;
         boolean useDepthBuffer = true;
         ensureRenderScript();
         // TODO: add parameters to layout
 
-        setOnLongClickListener(new OnLongClickListener() {
+        setOnLongClickListener(new View.OnLongClickListener() {
             public boolean onLongClick(View v) {
                 if (interpretLongPressEvents()) {
-                    mRenderScript.doLongPress();
+                    mController.onLongPress();
                     return true;
                 } else {
                     return false;
@@ -166,49 +133,32 @@
     private void ensureRenderScript() {
         if (mRS == null) {
             RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig();
-            sc.setDepth(16, 24);
+            if (USE_DEPTH_BUFFER) {
+                sc.setDepth(16, 24);
+            }
             mRS = createRenderScript(sc);
         }
         if (mRenderScript == null) {
-            mRenderScript = new CarouselRS(mRS, getResources(), getRenderScriptInfo().resId);
+            mRenderScript = new CarouselRS(mRS, mContext.getResources(),
+                    getRenderScriptInfo().resId);
             mRenderScript.resumeRendering();
         }
+        mController.setRS(mRS, mRenderScript);
     }
 
     @Override
     public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
         super.surfaceChanged(holder, format, w, h);
-        //mRS.contextSetSurface(w, h, holder.getSurface());
-        mRenderScript.resumeRendering();
-        setSlotCount(mSlotCount);
-        createCards(mCardCount);
-        setVisibleSlots(mVisibleSlots);
-        setVisibleDetails(mVisibleDetails);
-        setPrefetchCardCount(mPrefetchCardCount);
-        setDetailTextureAlignment(mDetailTextureAlignment);
-        setDrawRuler(mDrawRuler);
-        setCallback(mCarouselCallback);
-        setDefaultBitmap(mDefaultBitmap);
-        setLoadingBitmap(mLoadingBitmap);
-        setDefaultGeometry(mDefaultGeometry);
-        setLoadingGeometry(mLoadingGeometry);
-        setBackgroundColor(mBackgroundColor.x, mBackgroundColor.y, mBackgroundColor.z,
-                mBackgroundColor.w);
-        setBackgroundBitmap(mBackgroundBitmap);
-        setDetailLineBitmap(mDefaultLineBitmap);
-        setStartAngle(mStartAngle);
-        setCarouselRotationAngle(mCarouselRotationAngle);
-        setRadius(mRadius);
-        setCardRotation(mCardRotation);
-        setCardsFaceTangent(mCardsFaceTangent);
-        setSwaySensitivity(mSwaySensitivity);
-        setFrictionCoefficient(mFrictionCoefficient);
-        setDragFactor(mDragFactor);
-        setLookAt(mEye, mAt, mUp);
-        setRezInCardCount(mRezInCardCount);
-        setFadeInDuration(mFadeInDuration);
-        setDetailLoadingBitmap(mDetailLoadingBitmap);
-        setDrawCardsWithBlending(mDrawCardsWithBlending);
+        mController.onSurfaceChanged();
+    }
+
+    public CarouselController getController() {
+        return mController;
+    }
+
+    public void setController(CarouselController controller) {
+        mController = controller;
+        mController.setRS(mRS, mRenderScript);
     }
 
     /**
@@ -229,13 +179,7 @@
      * @return the loaded mesh or null if it cannot be loaded
      */
     public Mesh loadGeometry(int resId) {
-        Resources res = mContext.getResources();
-        FileA3D model = FileA3D.createFromResource(mRS, res, resId);
-        FileA3D.IndexEntry entry = model.getIndexEntry(0);
-        if(entry == null || entry.getClassID() != FileA3D.ClassID.MESH) {
-            return null;
-        }
-        return (Mesh) entry.getObject();
+        return mController.loadGeometry(mContext.getResources(), resId);
     }
 
     /**
@@ -244,9 +188,7 @@
      * @param resId
      */
     public void setGeometryForItem(int n, Mesh mesh) {
-        if (mRenderScript != null) {
-            mRenderScript.setGeometry(n, mesh);
-        }
+        mController.setGeometryForItem(n, mesh);
     }
 
     /**
@@ -256,10 +198,7 @@
      * @param n the number of slots
      */
     public void setSlotCount(int n) {
-        mSlotCount = n;
-        if (mRenderScript != null) {
-            mRenderScript.setSlotCount(n);
-        }
+        mController.setSlotCount(n);
     }
 
     /**
@@ -268,22 +207,7 @@
      * @param n the number of visible slots
      */
     public void setVisibleSlots(int n) {
-        mVisibleSlots = n;
-        if (mRenderScript != null) {
-            mRenderScript.setVisibleSlots(n);
-        }
-    }
-
-    /**
-     * Set the number of detail textures that can be visible at one time.
-     *
-     * @param n the number of slots
-     */
-    public void setVisibleDetails(int n) {
-        mVisibleDetails = n;
-        if (mRenderScript != null) {
-            mRenderScript.setVisibleDetails(n);
-        }
+        mController.setVisibleSlots(n);
     }
 
     /**
@@ -296,40 +220,36 @@
      * @param n the number of cards; should be even, so the count is the same on each side
      */
     public void setPrefetchCardCount(int n) {
-        mPrefetchCardCount = n;
-        if (mRenderScript != null) {
-            mRenderScript.setPrefetchCardCount(n);
-        }
+        mController.setPrefetchCardCount(n);
+    }
+
+    /**
+     * Set the number of detail textures that can be visible at one time.
+     *
+     * @param n the number of slots
+     */
+    public void setVisibleDetails(int n) {
+        mController.setVisibleDetails(n);
     }
 
     /**
      * Sets how detail textures are aligned with respect to the card.
-     *
+     * 
      * @param alignment a bitmask of DetailAlignment flags.
      */
     public void setDetailTextureAlignment(int alignment) {
-        int xBits = alignment & DetailAlignment.HORIZONTAL_ALIGNMENT_MASK;
-        if (xBits == 0 || ((xBits & (xBits - 1)) != 0)) {
-            throw new IllegalArgumentException(
-                  "Must specify exactly one horizontal alignment flag");
-        }
-        int yBits = alignment & DetailAlignment.VERTICAL_ALIGNMENT_MASK;
-        if (yBits == 0 || ((yBits & (yBits - 1)) != 0)) {
-          throw new IllegalArgumentException(
-                  "Must specify exactly one vertical alignment flag");
-        }
-
-        mDetailTextureAlignment = alignment;
-        if (mRenderScript != null) {
-            mRenderScript.setDetailTextureAlignment(alignment);
-        }
+        mController.setDetailTextureAlignment(alignment);
     }
 
+    /**
+     * Set whether blending is enabled while drawing the card textures. This should be true when
+     * translucent cards need to be supported, and false when all cards are fully opaque. Setting
+     * to false provides a performance boost.
+     *
+     * @param enabled True to enable blending, and false to disable it.
+     */
     public void setDrawCardsWithBlending(boolean enabled) {
-        mDrawCardsWithBlending = enabled;
-        if (mRenderScript != null) {
-            mRenderScript.setDrawCardsWithBlending(enabled);
-        }
+        mController.setDrawCardsWithBlending(enabled);
     }
 
     /**
@@ -338,10 +258,7 @@
      * @param drawRuler True to draw a ruler, false to draw nothing where the ruler would go.
      */
     public void setDrawRuler(boolean drawRuler) {
-        mDrawRuler = drawRuler;
-        if (mRenderScript != null) {
-            mRenderScript.setDrawRuler(drawRuler);
-        }
+        mController.setDrawRuler(drawRuler);
     }
 
     /**
@@ -353,14 +270,11 @@
      * @param n the number of cards to create.
      */
     public void createCards(int n) {
-        mCardCount = n;
-        if (mRenderScript != null) {
-            mRenderScript.createCards(n);
-        }
+        mController.createCards(n);
     }
 
     public int getCardCount() {
-        return mCardCount;
+        return mController.getCardCount();
     }
 
     /**
@@ -374,13 +288,7 @@
      * @param bitmap the bitmap image to show
      */
     public void setTextureForItem(int n, Bitmap bitmap) {
-        // Also check against mRS, to handle the case where the result is being delivered by a
-        // background thread but the sender no longer exists.
-        if (mRenderScript != null && mRS != null) {
-            if (DBG) Log.v(TAG, "setTextureForItem(" + n + ")");
-            mRenderScript.setTexture(n, bitmap);
-            if (DBG) Log.v(TAG, "done");
-        }
+        mController.setTextureForItem(n, bitmap);
     }
 
     /**
@@ -399,11 +307,7 @@
      */
     public void setDetailTextureForItem(int n, float offx, float offy, float loffx, float loffy,
             Bitmap bitmap) {
-        if (mRenderScript != null && mRS != null) {
-            if (DBG) Log.v(TAG, "setDetailTextureForItem(" + n + ")");
-            mRenderScript.setDetailTexture(n, offx, offy, loffx, loffy, bitmap);
-            if (DBG) Log.v(TAG, "done");
-        }
+        mController.setDetailTextureForItem(n, offx, offy, loffx, loffy, bitmap);
     }
 
     /**
@@ -415,10 +319,7 @@
      * @param bitmap
      */
     public void setDefaultBitmap(Bitmap bitmap) {
-        mDefaultBitmap = bitmap;
-        if (mRenderScript != null) {
-            mRenderScript.setDefaultBitmap(bitmap);
-        }
+        mController.setDefaultBitmap(bitmap);
     }
 
     /**
@@ -430,10 +331,7 @@
      * @param bitmap
      */
     public void setLoadingBitmap(Bitmap bitmap) {
-        mLoadingBitmap = bitmap;
-        if (mRenderScript != null) {
-            mRenderScript.setLoadingBitmap(bitmap);
-        }
+        mController.setLoadingBitmap(bitmap);
     }
 
     /**
@@ -446,10 +344,7 @@
      * @param alpha the amount of alpha
      */
     public void setBackgroundColor(float red, float green, float blue, float alpha) {
-        mBackgroundColor = new Float4(red, green, blue, alpha);
-        if (mRenderScript != null) {
-            mRenderScript.setBackgroundColor(mBackgroundColor);
-        }
+        mController.setBackgroundColor(red, green, blue, alpha);
     }
 
     /**
@@ -459,10 +354,7 @@
      * @param bitmap
      */
     public void setBackgroundBitmap(Bitmap bitmap) {
-        mBackgroundBitmap = bitmap;
-        if (mRenderScript != null) {
-            mRenderScript.setBackgroundTexture(bitmap);
-        }
+        mController.setBackgroundBitmap(bitmap);
     }
 
     /**
@@ -472,10 +364,7 @@
      * @param bitmap
      */
     public void setDetailLoadingBitmap(Bitmap bitmap) {
-        mDetailLoadingBitmap = bitmap;
-        if (mRenderScript != null) {
-            mRenderScript.setDetailLoadingTexture(bitmap);
-        }
+        mController.setDetailLoadingBitmap(bitmap);
     }
 
     /**
@@ -486,10 +375,7 @@
      * @param bitmap
      */
     public void setDetailLineBitmap(Bitmap bitmap) {
-        mDefaultLineBitmap = bitmap;
-        if (mRenderScript != null) {
-            mRenderScript.setDetailLineTexture(bitmap);
-        }
+        mController.setDetailLineBitmap(bitmap);
     }
 
     /**
@@ -499,10 +385,7 @@
      * @param mesh
      */
     public void setDefaultGeometry(Mesh mesh) {
-        mDefaultGeometry = mesh;
-        if (mRenderScript != null) {
-            mRenderScript.setDefaultGeometry(mesh);
-        }
+        mController.setDefaultGeometry(mesh);
     }
 
     /**
@@ -512,10 +395,7 @@
      * @param mesh
      */
     public void setLoadingGeometry(Mesh mesh) {
-        mLoadingGeometry = mesh;
-        if (mRenderScript != null) {
-            mRenderScript.setLoadingGeometry(mesh);
-        }
+        mController.setLoadingGeometry(mesh);
     }
 
     /**
@@ -525,10 +405,7 @@
      */
     public void setCallback(CarouselCallback callback)
     {
-        mCarouselCallback = callback;
-        if (mRenderScript != null) {
-            mRenderScript.setCallback(callback);
-        }
+        mController.setCallback(callback);
     }
 
     /**
@@ -540,78 +417,35 @@
      */
     public void setStartAngle(float angle)
     {
-        mStartAngle = angle;
-        if (mRenderScript != null) {
-            mRenderScript.setStartAngle(angle);
-        }
-    }
-
-    /**
-     * Set the current carousel rotation angle, in card units.
-     * This is measured in card positions, not in radians or degrees.
-     *
-     * A value of 0.0 means that card 0 is in the home position.
-     * A value of 1.0 means that card 1 is in the home position, and so on.
-     * The maximum value will be somewhat less than the total number of cards.
-     *
-     * @param angle
-     */
-    public void setCarouselRotationAngle(float angle) {
-        mCarouselRotationAngle = angle;
-        if (mRenderScript != null) {
-            mRenderScript.setCarouselRotationAngle(angle);
-        }
+        mController.setStartAngle(angle);
     }
 
     public void setRadius(float radius) {
-        mRadius = radius;
-        if (mRenderScript != null) {
-            mRenderScript.setRadius(radius);
-        }
+        mController.setRadius(radius);
     }
 
     public void setCardRotation(float cardRotation) {
-        mCardRotation = cardRotation;
-        if (mRenderScript != null) {
-            mRenderScript.setCardRotation(cardRotation);
-        }
+        mController.setCardRotation(cardRotation);
     }
 
     public void setCardsFaceTangent(boolean faceTangent) {
-        mCardsFaceTangent = faceTangent;
-        if (mRenderScript != null) {
-          mRenderScript.setCardsFaceTangent(faceTangent);
-        }
+        mController.setCardsFaceTangent(faceTangent);
     }
 
     public void setSwaySensitivity(float swaySensitivity) {
-        mSwaySensitivity = swaySensitivity;
-        if (mRenderScript != null) {
-            mRenderScript.setSwaySensitivity(swaySensitivity);
-        }
+        mController.setSwaySensitivity(swaySensitivity);
     }
 
     public void setFrictionCoefficient(float frictionCoefficient) {
-        mFrictionCoefficient = frictionCoefficient;
-        if (mRenderScript != null) {
-            mRenderScript.setFrictionCoefficient(frictionCoefficient);
-        }
+        mController.setFrictionCoefficient(frictionCoefficient);
     }
 
     public void setDragFactor(float dragFactor) {
-        mDragFactor = dragFactor;
-        if (mRenderScript != null) {
-            mRenderScript.setDragFactor(dragFactor);
-        }
+        mController.setDragFactor(dragFactor);
     }
 
     public void setLookAt(float[] eye, float[] at, float[] up) {
-        mEye = eye;
-        mAt = at;
-        mUp = up;
-        if (mRenderScript != null) {
-            mRenderScript.setLookAt(eye, at, up);
-        }
+        mController.setLookAt(eye, at, up);
     }
 
     /**
@@ -623,10 +457,7 @@
      * @param n the number of cards to rez in.
      */
     public void setRezInCardCount(float n) {
-        mRezInCardCount = n;
-        if (mRenderScript != null) {
-            mRenderScript.setRezInCardCount(n);
-        }
+        mController.setRezInCardCount(n);
     }
 
     /**
@@ -639,10 +470,7 @@
      * @param t
      */
     public void setFadeInDuration(long t) {
-        mFadeInDuration = t;
-        if (mRenderScript != null) {
-            mRenderScript.setFadeInDuration(t);
-        }
+        mController.setFadeInDuration(t);
     }
 
     @Override
@@ -653,6 +481,7 @@
             mRS = null;
             destroyRenderScript();
         }
+        mController.setRS(mRS, mRenderScript);
     }
 
     @Override
@@ -675,17 +504,17 @@
         switch (action) {
             case MotionEvent.ACTION_DOWN:
                 mTracking = true;
-                mRenderScript.doStart(x, y);
+                mController.onTouchStarted(x, y);
                 break;
 
             case MotionEvent.ACTION_MOVE:
                 if (mTracking) {
-                    mRenderScript.doMotion(x, y);
+                    mController.onTouchMoved(x, y);
                 }
                 break;
 
             case MotionEvent.ACTION_UP:
-                mRenderScript.doStop(x, y);
+                mController.onTouchStopped(x, y);
                 mTracking = false;
                 break;
         }
diff --git a/carousel/java/com/android/ex/carousel/CarouselViewHelper.java b/carousel/java/com/android/ex/carousel/CarouselViewHelper.java
index 44685c1..3a97880 100644
--- a/carousel/java/com/android/ex/carousel/CarouselViewHelper.java
+++ b/carousel/java/com/android/ex/carousel/CarouselViewHelper.java
@@ -257,11 +257,11 @@
     }
 
     public void onAnimationStarted() {
-        if (DBG) Log.v(TAG, "onAnimationStarted()");
+
     }
 
-    public void onAnimationFinished(float startAngle) {
-        if (DBG) Log.v(TAG, "onAnimationFinished(" + startAngle + ")");
+    public void onAnimationFinished(float carouselRotationAngle) {
+
     }
 
     public void onResume() {
diff --git a/carousel/java/com/android/ex/carousel/MVCCarouselView.java b/carousel/java/com/android/ex/carousel/MVCCarouselView.java
deleted file mode 100644
index abbf32a..0000000
--- a/carousel/java/com/android/ex/carousel/MVCCarouselView.java
+++ /dev/null
@@ -1,524 +0,0 @@
-/*
- * Copyright (C) 2010 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.ex.carousel;
-
-import android.view.View;
-import com.android.ex.carousel.CarouselRS.CarouselCallback;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.PixelFormat;
-import android.graphics.Bitmap.Config;
-import android.renderscript.FileA3D;
-import android.renderscript.Float4;
-import android.renderscript.Mesh;
-import android.renderscript.RSSurfaceView;
-import android.renderscript.RenderScriptGL;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.MotionEvent;
-import android.view.SurfaceHolder;
-
-/**
- * <p>
- * This class represents the basic building block for using a 3D Carousel. The Carousel is
- * basically a scene of cards and slots.  The spacing between cards is dictated by the number
- * of slots and the radius. The number of visible cards dictates how far the Carousel can be moved.
- * If the number of cards exceeds the number of slots, then the Carousel will continue to go
- * around until the last card can be seen.
- */
-public abstract class MVCCarouselView extends RSSurfaceView {
-    private static final boolean USE_DEPTH_BUFFER = true;
-    private static final String TAG = "MVCCarouselView";
-    private static final boolean DBG = false;
-    private CarouselRS mRenderScript;
-    private RenderScriptGL mRS;
-    private Context mContext;
-    private boolean mTracking;
-
-    CarouselController mController;
-
-    // Note: remember to update carousel.rs when changing the values below
-    public static class DetailAlignment {
-        /** Detail is centered vertically with respect to the card **/
-        public static final int CENTER_VERTICAL = 1;
-        /** Detail is aligned with the top edge of the carousel view **/
-        public static final int VIEW_TOP = 1 << 1;
-        /** Detail is aligned with the bottom edge of the carousel view (not yet implemented) **/
-        public static final int VIEW_BOTTOM = 1 << 2;
-        /** Detail is positioned above the card (not yet implemented) **/
-        public static final int ABOVE = 1 << 3;
-        /** Detail is positioned below the card **/
-        public static final int BELOW = 1 << 4;
-        /** Mask that selects those bits that control vertical alignment **/
-        public static final int VERTICAL_ALIGNMENT_MASK = 0xff;
-
-        /**
-         * Detail is centered horizontally with respect to either the top or bottom
-         * extent of the card, depending on whether the detail is above or below the card.
-         */
-        public static final int CENTER_HORIZONTAL = 1 << 8;
-        /**
-         * Detail is aligned with the left edge of either the top or the bottom of
-         * the card, depending on whether the detail is above or below the card.
-         */
-        public static final int LEFT = 1 << 9;
-        /**
-         * Detail is aligned with the right edge of either the top or the bottom of
-         * the card, depending on whether the detail is above or below the card.
-         * (not yet implemented)
-         */
-        public static final int RIGHT = 1 << 10;
-        /** Mask that selects those bits that control horizontal alignment **/
-        public static final int HORIZONTAL_ALIGNMENT_MASK = 0xff00;
-    }
-
-    public static class Info {
-        public Info(int _resId) { resId = _resId; }
-        public int resId; // resource for renderscript resource (e.g. R.raw.carousel)
-    }
-
-    public abstract Info getRenderScriptInfo();
-
-    public MVCCarouselView(Context context) {
-        this(context, new CarouselController());
-    }
-
-    public MVCCarouselView(Context context, CarouselController controller) {
-        this(context, null, controller);
-    }
-
-    /**
-     * Constructor used when this widget is created from a layout file.
-     */
-    public MVCCarouselView(Context context, AttributeSet attrs) {
-        this(context, attrs, new CarouselController());
-    }
-
-    public MVCCarouselView(Context context, AttributeSet attrs, CarouselController controller) {
-        super(context, attrs);
-        mContext = context;
-        mController = controller;
-        boolean useDepthBuffer = true;
-        ensureRenderScript();
-        // TODO: add parameters to layout
-
-        setOnLongClickListener(new View.OnLongClickListener() {
-            public boolean onLongClick(View v) {
-                if (interpretLongPressEvents()) {
-                    mController.onLongPress();
-                    return true;
-                } else {
-                    return false;
-                }
-            }
-        });
-    }
-
-    private void ensureRenderScript() {
-        if (mRS == null) {
-            RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig();
-            if (USE_DEPTH_BUFFER) {
-                sc.setDepth(16, 24);
-            }
-            mRS = createRenderScript(sc);
-        }
-        if (mRenderScript == null) {
-            mRenderScript = new CarouselRS(mRS, mContext.getResources(),
-                    getRenderScriptInfo().resId);
-            mRenderScript.resumeRendering();
-        }
-        mController.setRS(mRS, mRenderScript);
-    }
-
-    @Override
-    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
-        super.surfaceChanged(holder, format, w, h);
-        mController.onSurfaceChanged();
-    }
-
-    public CarouselController getController() {
-        return mController;
-    }
-
-    public void setController(CarouselController controller) {
-        mController = controller;
-        mController.setRS(mRS, mRenderScript);
-    }
-
-    /**
-     * Do I want to interpret the long-press gesture? If so, long-presses will cancel the
-     * current selection and call the appropriate callbacks. Otherwise, a long press will
-     * not be handled any way other than as a continued drag.
-     *
-     * @return True if we interpret long-presses
-     */
-    public boolean interpretLongPressEvents() {
-        return false;
-    }
-
-    /**
-     * Loads geometry from a resource id.
-     *
-     * @param resId
-     * @return the loaded mesh or null if it cannot be loaded
-     */
-    public Mesh loadGeometry(int resId) {
-        return mController.loadGeometry(mContext.getResources(), resId);
-    }
-
-    /**
-     * Load A3D file from resource.  If resId == 0, will clear geometry for this item.
-     * @param n
-     * @param resId
-     */
-    public void setGeometryForItem(int n, Mesh mesh) {
-        mController.setGeometryForItem(n, mesh);
-    }
-
-    /**
-     * Set the number of slots around the Carousel. Basically equivalent to the poles horses
-     * might attach to on a real Carousel.
-     *
-     * @param n the number of slots
-     */
-    public void setSlotCount(int n) {
-        mController.setSlotCount(n);
-    }
-
-    /**
-     * Sets the number of visible slots around the Carousel.  This is primarily used as a cheap
-     * form of clipping. The Carousel will never show more than this many cards.
-     * @param n the number of visible slots
-     */
-    public void setVisibleSlots(int n) {
-        mController.setVisibleSlots(n);
-    }
-
-    /**
-     * Set the number of cards to pre-load that are outside of the visible region, as determined by
-     * setVisibleSlots(). This number gets added to the number of visible slots and used to
-     * determine when resources for cards should be loaded. This number should be small (n <= 4)
-     * for systems with limited texture memory or views that show more than half dozen cards in the
-     * view.
-     *
-     * @param n the number of cards; should be even, so the count is the same on each side
-     */
-    public void setPrefetchCardCount(int n) {
-        mController.setPrefetchCardCount(n);
-    }
-
-    /**
-     * Set the number of detail textures that can be visible at one time.
-     *
-     * @param n the number of slots
-     */
-    public void setVisibleDetails(int n) {
-        mController.setVisibleDetails(n);
-    }
-
-    /**
-     * Sets how detail textures are aligned with respect to the card.
-     * 
-     * @param alignment a bitmask of DetailAlignment flags.
-     */
-    public void setDetailTextureAlignment(int alignment) {
-        mController.setDetailTextureAlignment(alignment);
-    }
-
-    /**
-     * Set whether blending is enabled while drawing the card textures. This should be true when
-     * translucent cards need to be supported, and false when all cards are fully opaque. Setting
-     * to false provides a performance boost.
-     *
-     * @param enabled True to enable blending, and false to disable it.
-     */
-    public void setDrawCardsWithBlending(boolean enabled) {
-        mController.setDrawCardsWithBlending(enabled);
-    }
-
-    /**
-     * Set whether to draw a ruler from the card to the detail texture
-     *
-     * @param drawRuler True to draw a ruler, false to draw nothing where the ruler would go.
-     */
-    public void setDrawRuler(boolean drawRuler) {
-        mController.setDrawRuler(drawRuler);
-    }
-
-    /**
-     * This dictates how many cards are in the deck.  If the number of cards is greater than the
-     * number of slots, then the Carousel goes around n / slot_count times.
-     *
-     * Can be called again to increase or decrease the number of cards.
-     *
-     * @param n the number of cards to create.
-     */
-    public void createCards(int n) {
-        mController.createCards(n);
-    }
-
-    public int getCardCount() {
-        return mController.getCardCount();
-    }
-
-    /**
-     * This sets the texture on card n.  It should only be called in response to
-     * {@link CarouselCallback#onRequestTexture(int)}.  Since there's no guarantee
-     * that a given texture is still on the screen, replacing this texture should be done
-     * by first setting it to null and then waiting for the next
-     * {@link CarouselCallback#onRequestTexture(int)} to swap it with the new one.
-     *
-     * @param n the card given by {@link CarouselCallback#onRequestTexture(int)}
-     * @param bitmap the bitmap image to show
-     */
-    public void setTextureForItem(int n, Bitmap bitmap) {
-        mController.setTextureForItem(n, bitmap);
-    }
-
-    /**
-     * This sets the detail texture that floats above card n. It should only be called in response
-     * to {@link CarouselCallback#onRequestDetailTexture(int)}.  Since there's no guarantee
-     * that a given texture is still on the screen, replacing this texture should be done
-     * by first setting it to null and then waiting for the next
-     * {@link CarouselCallback#onRequestDetailTexture(int)} to swap it with the new one.
-     *
-     * @param n the card to set detail texture for
-     * @param offx an optional offset to apply to the texture (in pixels) from top of detail line
-     * @param offy an optional offset to apply to the texture (in pixels) from top of detail line
-     * @param loffx an optional offset to apply to the line (in pixels) from left edge of card
-     * @param loffy an optional offset to apply to the line (in pixels) from top of screen
-     * @param bitmap the bitmap to show as the detail
-     */
-    public void setDetailTextureForItem(int n, float offx, float offy, float loffx, float loffy,
-            Bitmap bitmap) {
-        mController.setDetailTextureForItem(n, offx, offy, loffx, loffy, bitmap);
-    }
-
-    /**
-     * Sets the bitmap to show on a card when the card draws the very first time.
-     * Generally, this bitmap will only be seen during the first few frames of startup
-     * or when the number of cards are changed.  It can be ignored in most cases,
-     * as the cards will generally only be in the loading or loaded state.
-     *
-     * @param bitmap
-     */
-    public void setDefaultBitmap(Bitmap bitmap) {
-        mController.setDefaultBitmap(bitmap);
-    }
-
-    /**
-     * Sets the bitmap to show on the card while the texture is loading. It is set to this
-     * value just before {@link CarouselCallback#onRequestTexture(int)} is called and changed
-     * when {@link CarouselView#setTextureForItem(int, Bitmap)} is called. It is shared by all
-     * cards.
-     *
-     * @param bitmap
-     */
-    public void setLoadingBitmap(Bitmap bitmap) {
-        mController.setLoadingBitmap(bitmap);
-    }
-
-    /**
-     * Sets background to specified color.  If a background texture is specified with
-     * {@link CarouselView#setBackgroundBitmap(Bitmap)}, then this call has no effect.
-     *
-     * @param red the amount of red
-     * @param green the amount of green
-     * @param blue the amount of blue
-     * @param alpha the amount of alpha
-     */
-    public void setBackgroundColor(float red, float green, float blue, float alpha) {
-        mController.setBackgroundColor(red, green, blue, alpha);
-    }
-
-    /**
-     * Can be used to optionally set the background to a bitmap. When set to something other than
-     * null, this overrides {@link CarouselView#setBackgroundColor(Float4)}.
-     *
-     * @param bitmap
-     */
-    public void setBackgroundBitmap(Bitmap bitmap) {
-        mController.setBackgroundBitmap(bitmap);
-    }
-
-    /**
-     * Can be used to optionally set a "loading" detail bitmap. Typically, this is just a black
-     * texture with alpha = 0 to allow details to slowly fade in.
-     *
-     * @param bitmap
-     */
-    public void setDetailLoadingBitmap(Bitmap bitmap) {
-        mController.setDetailLoadingBitmap(bitmap);
-    }
-
-    /**
-     * This texture is used to draw a line from the card alongside the texture detail. The line
-     * will be as wide as the texture. It can be used to give the line glow effects as well as
-     * allowing other blending effects. It is typically one dimensional, e.g. 3x1.
-     *
-     * @param bitmap
-     */
-    public void setDetailLineBitmap(Bitmap bitmap) {
-        mController.setDetailLineBitmap(bitmap);
-    }
-
-    /**
-     * This geometry will be shown when no geometry has been loaded for a given slot. If not set,
-     * a quad will be drawn in its place. It is shared for all cards.
-     *
-     * @param mesh
-     */
-    public void setDefaultGeometry(Mesh mesh) {
-        mController.setDefaultGeometry(mesh);
-    }
-
-    /**
-     * This is an intermediate version of the object to show while geometry is loading. If not set,
-     * a quad will be drawn in its place.  It is shared for all cards.
-     *
-     * @param mesh
-     */
-    public void setLoadingGeometry(Mesh mesh) {
-        mController.setLoadingGeometry(mesh);
-    }
-
-    /**
-     * Sets the callback for receiving events from RenderScript.
-     *
-     * @param callback
-     */
-    public void setCallback(CarouselCallback callback)
-    {
-        mController.setCallback(callback);
-    }
-
-    /**
-     * Sets the startAngle for the Carousel. The start angle is the first position of the first
-     * slot draw.  Cards will be drawn from this angle in a counter-clockwise manner around the
-     * Carousel.
-     *
-     * @param angle the angle, in radians.
-     */
-    public void setStartAngle(float angle)
-    {
-        mController.setStartAngle(angle);
-    }
-
-    public void setRadius(float radius) {
-        mController.setRadius(radius);
-    }
-
-    public void setCardRotation(float cardRotation) {
-        mController.setCardRotation(cardRotation);
-    }
-
-    public void setCardsFaceTangent(boolean faceTangent) {
-        mController.setCardsFaceTangent(faceTangent);
-    }
-
-    public void setSwaySensitivity(float swaySensitivity) {
-        mController.setSwaySensitivity(swaySensitivity);
-    }
-
-    public void setFrictionCoefficient(float frictionCoefficient) {
-        mController.setFrictionCoefficient(frictionCoefficient);
-    }
-
-    public void setDragFactor(float dragFactor) {
-        mController.setDragFactor(dragFactor);
-    }
-
-    public void setLookAt(float[] eye, float[] at, float[] up) {
-        mController.setLookAt(eye, at, up);
-    }
-
-    /**
-     * This sets the number of cards in the distance that will be shown "rezzing in".
-     * These alpha values will be faded in from the background to the foreground over
-     * 'n' cards.  A floating point value is used to allow subtly changing the rezzing in
-     * position.
-     *
-     * @param n the number of cards to rez in.
-     */
-    public void setRezInCardCount(float n) {
-        mController.setRezInCardCount(n);
-    }
-
-    /**
-     * This sets the duration (in ms) that a card takes to fade in when loaded via a call
-     * to {@link CarouselView#setTextureForItem(int, Bitmap)}. The timer starts the
-     * moment {@link CarouselView#setTextureForItem(int, Bitmap)} is called and continues
-     * until all of the cards have faded in.  Note: using large values will extend the
-     * animation until all cards have faded in.
-     *
-     * @param t
-     */
-    public void setFadeInDuration(long t) {
-        mController.setFadeInDuration(t);
-    }
-
-    @Override
-    protected void onDetachedFromWindow() {
-        super.onDetachedFromWindow();
-        mRenderScript = null;
-        if (mRS != null) {
-            mRS = null;
-            destroyRenderScript();
-        }
-        mController.setRS(mRS, mRenderScript);
-    }
-
-    @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        ensureRenderScript();
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        super.onTouchEvent(event);
-        final int action = event.getAction();
-        final float x = event.getX();
-        final float y = event.getY();
-
-        if (mRenderScript == null) {
-            return true;
-        }
-
-        switch (action) {
-            case MotionEvent.ACTION_DOWN:
-                mTracking = true;
-                mController.onTouchStarted(x, y);
-                break;
-
-            case MotionEvent.ACTION_MOVE:
-                if (mTracking) {
-                    mController.onTouchMoved(x, y);
-                }
-                break;
-
-            case MotionEvent.ACTION_UP:
-                mController.onTouchStopped(x, y);
-                mTracking = false;
-                break;
-        }
-
-        return true;
-    }
-}
diff --git a/carousel/java/com/android/ex/carousel/MVCCarouselViewHelper.java b/carousel/java/com/android/ex/carousel/MVCCarouselViewHelper.java
deleted file mode 100644
index 419797f..0000000
--- a/carousel/java/com/android/ex/carousel/MVCCarouselViewHelper.java
+++ /dev/null
@@ -1,290 +0,0 @@
-package com.android.ex.carousel;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Matrix;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.Message;
-import android.renderscript.Mesh;
-import android.util.Log;
-
-import com.android.ex.carousel.CarouselRS.CarouselCallback;
-
-/**
- * MVCCarouselViewHelper wraps all of the threading and event handling of the MVCCarouselView,
- * providing a simpler interface.  Most users will just need to implement a handful of
- * methods to get an application working.
- *
- */
-public class MVCCarouselViewHelper implements CarouselCallback {
-    private static final String TAG = "MVCCarouselViewHelper";
-    private static final int SET_TEXTURE_N = 1;
-    private static final int SET_DETAIL_TEXTURE_N = 2;
-    private static final int SET_GEOMETRY_N = 3;
-
-    // This is an ordered list of base message ids to allow removal of a single item from the
-    // list for a particular card. The implementation currently supports up to a million cards.
-    private static final int REQUEST_TEXTURE_N = 1000000;
-    private static final int REQUEST_DETAIL_TEXTURE_N = 2000000;
-    private static final int REQUEST_GEOMETRY_N = 3000000;
-    private static final int REQUEST_END = 4000000;
-
-    private HandlerThread mHandlerThread;
-    private Context mContext;
-    private MVCCarouselView mCarouselView;
-    private boolean DBG = false;
-    private long HOLDOFF_DELAY = 100;
-    private Handler mAsyncHandler; // Background thread handler for reading textures, geometry, etc.
-    private Handler mSyncHandler; // Synchronous handler for interacting with UI elements.
-
-    public static class TextureParameters {
-        public TextureParameters(Matrix _matrix) { matrix = _matrix; }
-        public Matrix matrix;
-    };
-
-    public static class DetailTextureParameters {
-        public DetailTextureParameters(float textureOffsetX, float textureOffsetY) {
-            this.textureOffsetX = textureOffsetX;
-            this.textureOffsetY = textureOffsetY;
-            this.lineOffsetX = 0.0f;
-            this.lineOffsetY = 0.0f;
-        }
-        public DetailTextureParameters(
-                float textureOffsetX, float textureOffsetY,
-                float lineOffsetX, float lineOffsetY) {
-            this.textureOffsetX = textureOffsetX;
-            this.textureOffsetY = textureOffsetY;
-            this.lineOffsetX = lineOffsetX;
-            this.lineOffsetY = lineOffsetY;
-        }
-        public float textureOffsetX;
-        public float textureOffsetY;
-        public float lineOffsetX;
-        public float lineOffsetY;
-    };
-
-    public void setCarouselView(MVCCarouselView carouselView) {
-        mCarouselView = carouselView;
-        mCarouselView.setCallback(this);
-    }
-
-    public MVCCarouselViewHelper(Context context, MVCCarouselView carouselView) {
-        this(context);
-        setCarouselView(carouselView);
-    }
-
-    public MVCCarouselViewHelper(Context context) {
-        mContext = context;
-
-        mHandlerThread = new HandlerThread(TAG + ".handler");
-        mHandlerThread.start();
-
-        mAsyncHandler = new AsyncHandler(mHandlerThread.getLooper());
-        mSyncHandler = new SyncHandler(); // runs in calling thread
-    }
-
-    class AsyncHandler extends Handler {
-        AsyncHandler(Looper looper) {
-            super(looper);
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            int id = msg.arg1;
-            if (id >= mCarouselView.getCardCount()) {
-                Log.e(TAG, "Index out of range for get, card:" + id);
-                return;
-            }
-            if (msg.what < REQUEST_TEXTURE_N || msg.what > REQUEST_END) {
-                Log.e(TAG, "Unknown message: " + id);
-                return;
-            }
-            if (msg.what < REQUEST_DETAIL_TEXTURE_N) {
-                // REQUEST_TEXTURE_N
-                final Bitmap bitmap = getTexture(id);
-                if (bitmap != null) {
-                    mSyncHandler.obtainMessage(SET_TEXTURE_N, id, 0, bitmap).sendToTarget();
-                }
-            } else if (msg.what < REQUEST_GEOMETRY_N) {
-                // REQUEST_DETAIL_TEXTURE_N
-                final Bitmap bitmap = getDetailTexture(id);
-                if (bitmap != null) {
-                    mSyncHandler.obtainMessage(SET_DETAIL_TEXTURE_N, id, 0, bitmap).sendToTarget();
-                }
-            } else if (msg.what < REQUEST_END) {
-                // REQUEST_GEOMETRY_N
-                Mesh mesh = getGeometry(id);
-                if (mesh != null) {
-                    mSyncHandler.obtainMessage(SET_GEOMETRY_N, id, 0, mesh).sendToTarget();
-                }
-            }
-        }
-    };
-
-    class SyncHandler extends Handler {
-        @Override
-        public void handleMessage(Message msg) {
-            int id = msg.arg1;
-            if (id >= mCarouselView.getCardCount()) {
-                Log.e(TAG, "Index out of range for set, card:" + id);
-                return;
-            }
-
-            switch (msg.what) {
-                case SET_TEXTURE_N:
-                    mCarouselView.setTextureForItem(id, (Bitmap) msg.obj);
-                    break;
-
-                case SET_DETAIL_TEXTURE_N:
-                    DetailTextureParameters params = getDetailTextureParameters(id);
-                    float x = params != null ? params.textureOffsetX : 0.0f;
-                    float y = params != null ? params.textureOffsetY : 0.0f;
-                    float lx = params != null ? params.lineOffsetX : 0.0f;
-                    float ly = params != null ? params.lineOffsetY : 0.0f;
-                    mCarouselView.setDetailTextureForItem(id, x, y, lx, ly, (Bitmap) msg.obj);
-                    break;
-
-                case SET_GEOMETRY_N:
-                    mCarouselView.setGeometryForItem(id, (Mesh) msg.obj);
-                    break;
-            }
-        }
-    };
-
-    /**
-     * Implement this method if you want to load a texture for
-     * the given card.  Most subclasses will implement this. Note: this will generally
-     * <b>not</b> be called in the UI thread, so proper locking should be ensured.
-     *
-     * @param id of the texture to load
-     * @return a valid bitmap
-     */
-    public Bitmap getTexture(int id) {
-        return null;
-    }
-
-    /**
-     * Implement this method if you want to load a detail texture for
-     * the given card.  Most subclasses will implement this. Note: this will generally
-     * <b>not</b> be called in the UI thread, so proper locking should be ensured.
-     *
-     * @param id
-     * @return
-     */
-    public Bitmap getDetailTexture(int id) {
-        return null;
-    }
-
-    /**
-     * Implement this method if you want to load geometry for the given card.  Most subclasses
-     * will implement this. Note: this will generally <b>not</b> be called in the UI thread,
-     * so proper locking should be ensured.
-     *
-     * @param id
-     * @return
-     */
-    public Mesh getGeometry(int id) {
-        return null;
-    }
-
-    /**
-     * Implement this method if you want custom texture parameters for
-     * the given id. Note: this will generally
-     * <b>not</b> be called in the UI thread, so proper locking should be ensured.
-     *
-     * @param id
-     * @return texture parameters
-     */
-    public TextureParameters getTextureParameters(int id) {
-        return null;
-    }
-
-    /**
-     * Implement this method if you want custom detail texture parameters for
-     * the given id. Note: this will generally
-     * <b>not</b> be called in the UI thread, so proper locking should be ensured.
-     *
-     * @param id the id of the texture being requested
-     * @return detail texture parameters
-     */
-    public DetailTextureParameters getDetailTextureParameters(int id) {
-        return null;
-    }
-
-    public void onRequestTexture(int id) {
-        if (DBG) Log.v(TAG, "onRequestTexture(" + id + ")" );
-        mAsyncHandler.removeMessages(REQUEST_TEXTURE_N + id);
-        Message message = mAsyncHandler.obtainMessage(REQUEST_TEXTURE_N + id, id, 0);
-        mAsyncHandler.sendMessageDelayed(message, HOLDOFF_DELAY);
-    }
-
-    public void onInvalidateTexture(final int id) {
-        if (DBG) Log.v(TAG, "onInvalidateTexture(" + id + ")");
-        mAsyncHandler.removeMessages(REQUEST_TEXTURE_N + id);
-    }
-
-    public void onRequestGeometry(int id) {
-        if (DBG) Log.v(TAG, "onRequestGeometry(" + id + ")");
-        mAsyncHandler.removeMessages(REQUEST_GEOMETRY_N + id);
-        mAsyncHandler.sendMessage(mAsyncHandler.obtainMessage(REQUEST_GEOMETRY_N + id, id, 0));
-    }
-
-    public void onInvalidateGeometry(int id) {
-        if (DBG) Log.v(TAG, "onInvalidateGeometry(" + id + ")");
-        mAsyncHandler.removeMessages(REQUEST_GEOMETRY_N + id);
-    }
-
-    public void onRequestDetailTexture(int id) {
-        if (DBG) Log.v(TAG, "onRequestDetailTexture(" + id + ")" );
-        mAsyncHandler.removeMessages(REQUEST_DETAIL_TEXTURE_N + id);
-        Message message = mAsyncHandler.obtainMessage(REQUEST_DETAIL_TEXTURE_N + id, id, 0);
-        mAsyncHandler.sendMessageDelayed(message, HOLDOFF_DELAY);
-    }
-
-    public void onInvalidateDetailTexture(int id) {
-        if (DBG) Log.v(TAG, "onInvalidateDetailTexture(" + id + ")");
-        mAsyncHandler.removeMessages(REQUEST_DETAIL_TEXTURE_N + id);
-    }
-
-    public void onCardSelected(int n) {
-        if (DBG) Log.v(TAG, "onCardSelected(" + n + ")");
-    }
-
-    public void onCardLongPress(int n) {
-        if (DBG) Log.v(TAG, "onCardLongPress(" + n + ")");
-    }
-
-    public void onAnimationStarted() {
-
-    }
-
-    public void onAnimationFinished(float carouselRotationAngle) {
-
-    }
-
-    public void onReportFirstCardPosition(int n) {
-
-    }
-
-    public void onResume() {
-        mCarouselView.onResume();
-    }
-
-    public void onPause() {
-        mCarouselView.onPause();
-    }
-
-    public void onDestroy() {
-        mHandlerThread.quit();
-    }
-
-    protected Handler getAsyncHandler() {
-        return mAsyncHandler;
-    }
-
-    protected MVCCarouselView getCarouselView() {
-        return mCarouselView;
-    }
-}
diff --git a/carousel/test/src/com/android/carouseltest/CarouselTestActivity.java b/carousel/test/src/com/android/carouseltest/CarouselTestActivity.java
index 8c1cffd..6f7b846 100644
--- a/carousel/test/src/com/android/carouseltest/CarouselTestActivity.java
+++ b/carousel/test/src/com/android/carouseltest/CarouselTestActivity.java
@@ -17,6 +17,7 @@
 package com.android.carouseltest;
 
 import com.android.carouseltest.MyCarouselView;
+import com.android.ex.carousel.CarouselController;
 import com.android.ex.carousel.CarouselView;
 import com.android.ex.carousel.CarouselViewHelper;
 
@@ -45,6 +46,7 @@
     private static final int DETAIL_TEXTURE_HEIGHT = 80;
     private static final int VISIBLE_DETAIL_COUNT = 3;
     private static final boolean INCREMENTAL_ADD = false; // To debug incrementally adding cards
+    private CarouselController mController;
     private CarouselView mView;
     private Paint mPaint = new Paint();
     private CarouselViewHelper mHelper;
@@ -119,7 +121,8 @@
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
-        mView = new MyCarouselView(this);
+        mController = new CarouselController();
+        mView = new MyCarouselView(this, mController);
         mView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
         mPaint.setColor(0xffffffff);
         final Resources res = getResources();
diff --git a/carousel/test/src/com/android/carouseltest/MyCarouselView.java b/carousel/test/src/com/android/carouseltest/MyCarouselView.java
index b9ee6b1..f028e6c 100644
--- a/carousel/test/src/com/android/carouseltest/MyCarouselView.java
+++ b/carousel/test/src/com/android/carouseltest/MyCarouselView.java
@@ -19,17 +19,22 @@
 import android.content.Context;
 import android.util.AttributeSet;
 
+import com.android.ex.carousel.CarouselController;
 import com.android.ex.carousel.CarouselView;
 import com.android.ex.carousel.CarouselView.Info;
 
 public class MyCarouselView extends CarouselView {
 
-    public MyCarouselView(Context context) {
-        this(context, null);
+    public MyCarouselView(Context context, CarouselController controller) {
+        this(context, null, controller);
     }
 
     public MyCarouselView(Context context, AttributeSet attrs) {
-        super(context, attrs);
+        this(context, attrs, new CarouselController());
+    }
+
+    public MyCarouselView(Context context, AttributeSet attrs, CarouselController controller) {
+        super(context, attrs, controller);
     }
 
     public Info getRenderScriptInfo() {
diff --git a/carousel/test/src/com/android/carouseltest/TaskSwitcherActivity.java b/carousel/test/src/com/android/carouseltest/TaskSwitcherActivity.java
index 5199fa1..d6c4829 100644
--- a/carousel/test/src/com/android/carouseltest/TaskSwitcherActivity.java
+++ b/carousel/test/src/com/android/carouseltest/TaskSwitcherActivity.java
@@ -21,6 +21,7 @@
 import java.util.List;
 import com.android.carouseltest.R;
 
+import com.android.ex.carousel.CarouselController;
 import com.android.ex.carousel.CarouselViewHelper;
 
 import android.app.Activity;
@@ -58,6 +59,7 @@
     private boolean mPortraitMode = true;
     private ArrayList<ActivityDescription> mActivityDescriptions
             = new ArrayList<ActivityDescription>();
+    private CarouselController mController;
     private MyCarouselView mView;
     private Bitmap mBlankBitmap = Bitmap.createBitmap(128, 128, Config.RGB_565);
     private LocalCarouselViewHelper mHelper;
@@ -200,7 +202,8 @@
         final Resources res = getResources();
         final View decorView = getWindow().getDecorView();
 
-        mView = new MyCarouselView(this);
+        mController = new CarouselController();
+        mView = new MyCarouselView(this, mController);
         mHelper = new LocalCarouselViewHelper(this);
         mHelper.setCarouselView(mView);
         mView.setSlotCount(CARD_SLOTS);