Merge "Log null returns from Camera.getParameters" into lmp-dev
diff --git a/camera2/Android.mk b/camera2/Android.mk
index 9ac4a8a..3719578 100644
--- a/camera2/Android.mk
+++ b/camera2/Android.mk
@@ -12,4 +12,5 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# Build all subprojects
 include $(call all-subdir-makefiles)
diff --git a/camera2/portability/src/com/android/ex/camera2/portability/AndroidCamera2AgentImpl.java b/camera2/portability/src/com/android/ex/camera2/portability/AndroidCamera2AgentImpl.java
index e675796..62cb700 100644
--- a/camera2/portability/src/com/android/ex/camera2/portability/AndroidCamera2AgentImpl.java
+++ b/camera2/portability/src/com/android/ex/camera2/portability/AndroidCamera2AgentImpl.java
@@ -35,6 +35,7 @@
 import android.hardware.camera2.params.MeteringRectangle;
 import android.media.Image;
 import android.media.ImageReader;
+import android.media.MediaActionSound;
 import android.os.Build;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -63,6 +64,7 @@
     private final CameraStateHolder mCameraState;
     private final DispatchThread mDispatchThread;
     private final CameraManager mCameraManager;
+    private final MediaActionSound mNoisemaker;
 
     /**
      * Number of camera devices.  The length of {@code mCameraDevices} does not reveal this
@@ -88,6 +90,8 @@
         mDispatchThread = new DispatchThread(mCameraHandler, mCameraHandlerThread);
         mDispatchThread.start();
         mCameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
+        mNoisemaker = new MediaActionSound();
+        mNoisemaker.load(MediaActionSound.SHUTTER_CLICK);
 
         mNumCameraDevices = 0;
         mCameraDevices = new ArrayList<String>();
@@ -156,7 +160,7 @@
     }
 
     private static abstract class CaptureAvailableListener
-            extends CameraCaptureSession.CaptureListener
+            extends CameraCaptureSession.CaptureCallback
             implements ImageReader.OnImageAvailableListener {};
 
     private class Camera2Handler extends HistoryHandler {
@@ -194,6 +198,9 @@
         // Available whenever setAutoFocusMoveCallback() was last invoked with a non-null argument:
         private CameraAFMoveCallback mPassiveAfCallback;
 
+        // Gets reset on every state change
+        private int mCurrentAeState = CaptureResult.CONTROL_AE_STATE_INACTIVE;
+
         Camera2Handler(Looper looper) {
             super(looper);
         }
@@ -208,7 +215,7 @@
                         CameraOpenCallback openCallback = (CameraOpenCallback) msg.obj;
                         int cameraIndex = msg.arg1;
 
-                        if (mCameraState.getState() != AndroidCamera2StateHolder.CAMERA_UNOPENED) {
+                        if (mCameraState.getState() > AndroidCamera2StateHolder.CAMERA_UNOPENED) {
                             openCallback.onDeviceOpenedAlready(cameraIndex,
                                     generateHistoryString(cameraIndex));
                             break;
@@ -224,7 +231,7 @@
                             mOpenCallback.onCameraDisabled(msg.arg1);
                             break;
                         }
-                        mCameraManager.openCamera(mCameraId, mCameraDeviceStateListener, this);
+                        mCameraManager.openCamera(mCameraId, mCameraDeviceStateCallback, this);
 
                         break;
                     }
@@ -259,7 +266,7 @@
                         mPhotoSize = null;
                         mCameraIndex = 0;
                         mCameraId = null;
-                        mCameraState.setState(AndroidCamera2StateHolder.CAMERA_UNOPENED);
+                        changeState(AndroidCamera2StateHolder.CAMERA_UNOPENED);
                         break;
                     }
 
@@ -285,19 +292,23 @@
                         }
 
                         mOneshotPreviewingCallback = (CameraStartPreviewCallback) msg.obj;
-                        mCameraState.setState(AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE);
+                        changeState(AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE);
                         try {
                             mSession.setRepeatingRequest(
                                     mPersistentSettings.createRequest(mCamera,
                                             CameraDevice.TEMPLATE_PREVIEW, mPreviewSurface),
-                                    /*listener*/mCameraFocusStateListener, /*handler*/this);
+                                    /*listener*/mCameraResultStateCallback, /*handler*/this);
                         } catch(CameraAccessException ex) {
                             Log.w(TAG, "Unable to start preview", ex);
-                            mCameraState.setState(AndroidCamera2StateHolder.CAMERA_PREVIEW_READY);
+                            changeState(AndroidCamera2StateHolder.CAMERA_PREVIEW_READY);
                         }
                         break;
                     }
 
+                    // FIXME: We need to tear down the CameraCaptureSession here
+                    // (and unlock the CameraSettings object from our
+                    // CameraProxy) so that the preview/photo sizes can be
+                    // changed again while no preview is running.
                     case CameraActions.STOP_PREVIEW: {
                         if (mCameraState.getState() <
                                         AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE) {
@@ -306,7 +317,7 @@
                         }
 
                         mSession.stopRepeating();
-                        mCameraState.setState(AndroidCamera2StateHolder.CAMERA_PREVIEW_READY);
+                        changeState(AndroidCamera2StateHolder.CAMERA_PREVIEW_READY);
                         break;
                     }
 
@@ -364,19 +375,39 @@
                         }
 
                         // The earliest we can reliably tell whether the autofocus has locked in
-                        // response to our latest request is when our one-time capture completes.
+                        // response to our latest request is when our one-time capture progresses.
                         // However, it will probably take longer than that, so once that happens,
                         // just start checking the repeating preview requests as they complete.
                         final CameraAFCallback callback = (CameraAFCallback) msg.obj;
-                        CameraCaptureSession.CaptureListener deferredCallbackSetter =
-                                new CameraCaptureSession.CaptureListener() {
+                        CameraCaptureSession.CaptureCallback deferredCallbackSetter =
+                                new CameraCaptureSession.CaptureCallback() {
+                            private boolean mAlreadyDispatched = false;
+
+                            @Override
+                            public void onCaptureProgressed(CameraCaptureSession session,
+                                                            CaptureRequest request,
+                                                            CaptureResult result) {
+                                checkAfState(result);
+                            }
+
                             @Override
                             public void onCaptureCompleted(CameraCaptureSession session,
                                                            CaptureRequest request,
                                                            TotalCaptureResult result) {
-                                // Now our mCameraFocusStateListener will invoke the callback the
-                                // first time it finds the focus motor to be locked.
-                                mOneshotAfCallback = callback;
+                                checkAfState(result);
+                            }
+
+                            private void checkAfState(CaptureResult result) {
+                                if (result.get(CaptureResult.CONTROL_AF_STATE) != null &&
+                                        !mAlreadyDispatched) {
+                                    // Now our mCameraResultStateCallback will invoke the callback
+                                    // the first time it finds the focus motor to be locked.
+                                    mAlreadyDispatched = true;
+                                    mOneshotAfCallback = callback;
+                                    // This is an optimization: check the AF state of this frame
+                                    // instead of simply waiting for the next.
+                                    mCameraResultStateCallback.monitorControlStates(result);
+                                }
                             }
 
                             @Override
@@ -388,7 +419,7 @@
                             }};
 
                         // Send a one-time capture to trigger the camera driver to lock focus.
-                        mCameraState.setState(AndroidCamera2StateHolder.CAMERA_FOCUS_LOCKED);
+                        changeState(AndroidCamera2StateHolder.CAMERA_FOCUS_LOCKED);
                         Camera2RequestSettingsSet trigger =
                                 new Camera2RequestSettingsSet(mPersistentSettings);
                         trigger.set(CaptureRequest.CONTROL_AF_TRIGGER,
@@ -400,7 +431,7 @@
                                     /*listener*/deferredCallbackSetter, /*handler*/ this);
                         } catch(CameraAccessException ex) {
                             Log.e(TAG, "Unable to lock autofocus", ex);
-                            mCameraState.setState(AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE);
+                            changeState(AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE);
                         }
                         break;
                     }
@@ -414,7 +445,7 @@
                         }
 
                         // Send a one-time capture to trigger the camera driver to resume scanning.
-                        mCameraState.setState(AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE);
+                        changeState(AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE);
                         Camera2RequestSettingsSet cancel =
                                 new Camera2RequestSettingsSet(mPersistentSettings);
                         cancel.set(CaptureRequest.CONTROL_AF_TRIGGER,
@@ -426,8 +457,7 @@
                                     /*listener*/null, /*handler*/this);
                         } catch(CameraAccessException ex) {
                             Log.e(TAG, "Unable to cancel autofocus", ex);
-                            mCameraState.setState(
-                                    AndroidCamera2StateHolder.CAMERA_FOCUS_LOCKED);
+                            changeState(AndroidCamera2StateHolder.CAMERA_FOCUS_LOCKED);
                         }
                         break;
                     }
@@ -482,8 +512,21 @@
 
                         final CaptureAvailableListener listener =
                                 (CaptureAvailableListener) msg.obj;
-                        if (mLegacyDevice) {
-                            // Just snap the shot
+                        if (mLegacyDevice ||
+                                (mCurrentAeState == CaptureResult.CONTROL_AE_STATE_CONVERGED &&
+                                !mPersistentSettings.matches(CaptureRequest.CONTROL_AE_MODE,
+                                        CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH) &&
+                                !mPersistentSettings.matches(CaptureRequest.FLASH_MODE,
+                                        CaptureRequest.FLASH_MODE_SINGLE)))
+                                {
+                            // Legacy devices don't support the precapture state keys and instead
+                            // perform autoexposure convergence automatically upon capture.
+
+                            // On other devices, as long as it has already converged, it determined
+                            // that flash was not required, and we're not going to invalidate the
+                            // current exposure levels by forcing the force on, we can save
+                            // significant capture time by not forcing a recalculation.
+                            Log.i(TAG, "Skipping pre-capture autoexposure convergence");
                             mCaptureReader.setOnImageAvailableListener(listener, /*handler*/this);
                             try {
                                 mSession.capture(
@@ -492,17 +535,42 @@
                                                 mCaptureReader.getSurface()),
                                         listener, /*handler*/this);
                             } catch (CameraAccessException ex) {
-                                Log.e(TAG, "Unable to initiate legacy capture", ex);
+                                Log.e(TAG, "Unable to initiate immediate capture", ex);
                             }
                         } else {
-                            // Not a legacy device, so we need to let AE converge before capturing
-                            CameraCaptureSession.CaptureListener deferredCallbackSetter =
-                                    new CameraCaptureSession.CaptureListener() {
+                            // We need to let AE converge before capturing. Once our one-time
+                            // trigger capture has made it into the pipeline, we'll start checking
+                            // for the completion of that convergence, capturing when that happens.
+                            Log.i(TAG, "Forcing pre-capture autoexposure convergence");
+                            CameraCaptureSession.CaptureCallback deferredCallbackSetter =
+                                    new CameraCaptureSession.CaptureCallback() {
+                                private boolean mAlreadyDispatched = false;
+
+                                @Override
+                                public void onCaptureProgressed(CameraCaptureSession session,
+                                                                CaptureRequest request,
+                                                                CaptureResult result) {
+                                    checkAeState(result);
+                                }
+
                                 @Override
                                 public void onCaptureCompleted(CameraCaptureSession session,
                                                                CaptureRequest request,
                                                                TotalCaptureResult result) {
-                                    mOneshotCaptureCallback = listener;
+                                    checkAeState(result);
+                                }
+
+                                private void checkAeState(CaptureResult result) {
+                                    if (result.get(CaptureResult.CONTROL_AE_STATE) != null &&
+                                            !mAlreadyDispatched) {
+                                        // Now our mCameraResultStateCallback will invoke the
+                                        // callback once the autoexposure routine has converged.
+                                        mAlreadyDispatched = true;
+                                        mOneshotCaptureCallback = listener;
+                                        // This is an optimization: check the AE state of this frame
+                                        // instead of simply waiting for the next.
+                                        mCameraResultStateCallback.monitorControlStates(result);
+                                    }
                                 }
 
                                 @Override
@@ -595,13 +663,13 @@
                     mSession.setRepeatingRequest(
                             mPersistentSettings.createRequest(mCamera,
                                     CameraDevice.TEMPLATE_PREVIEW, mPreviewSurface),
-                            /*listener*/mCameraFocusStateListener, /*handler*/this);
+                            /*listener*/mCameraResultStateCallback, /*handler*/this);
                 } catch (CameraAccessException ex) {
                     Log.e(TAG, "Failed to apply updated request settings", ex);
                 }
             } else if (mCameraState.getState() < AndroidCamera2StateHolder.CAMERA_PREVIEW_READY) {
                 // If we're already ready to preview, this doesn't regress our state
-                mCameraState.setState(AndroidCamera2StateHolder.CAMERA_CONFIGURED);
+                changeState(AndroidCamera2StateHolder.CAMERA_CONFIGURED);
             }
         }
 
@@ -642,7 +710,7 @@
             try {
                 mCamera.createCaptureSession(
                         Arrays.asList(mPreviewSurface, mCaptureReader.getSurface()),
-                        mCameraPreviewStateListener, this);
+                        mCameraPreviewStateCallback, this);
             } catch (CameraAccessException ex) {
                 Log.e(TAG, "Failed to create camera capture session", ex);
             }
@@ -655,12 +723,22 @@
             } catch (CameraAccessException ex) {
                 Log.e(TAG, "Failed to close existing camera capture session", ex);
             }
-            mCameraState.setState(AndroidCamera2StateHolder.CAMERA_CONFIGURED);
+            changeState(AndroidCamera2StateHolder.CAMERA_CONFIGURED);
         }
 
-        // This listener monitors our connection to and disconnection from camera devices.
-        private CameraDevice.StateListener mCameraDeviceStateListener =
-                new CameraDevice.StateListener() {
+        private void changeState(int newState) {
+            if (mCameraState.getState() != newState) {
+                mCameraState.setState(newState);
+                if (newState < AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE) {
+                    mCurrentAeState = CaptureResult.CONTROL_AE_STATE_INACTIVE;
+                    mCameraResultStateCallback.resetState();
+                }
+            }
+        }
+
+        // This callback monitors our connection to and disconnection from camera devices.
+        private CameraDevice.StateCallback mCameraDeviceStateCallback =
+                new CameraDevice.StateCallback() {
             @Override
             public void onOpened(CameraDevice camera) {
                 mCamera = camera;
@@ -676,7 +754,7 @@
                         mLegacyDevice =
                                 props.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL) ==
                                         CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY;
-                        mCameraState.setState(AndroidCamera2StateHolder.CAMERA_UNCONFIGURED);
+                        changeState(AndroidCamera2StateHolder.CAMERA_UNCONFIGURED);
                         mOpenCallback.onCameraOpened(mCameraProxy);
                     } catch (CameraAccessException ex) {
                         mOpenCallback.onDeviceOpenFailure(mCameraIndex,
@@ -700,13 +778,13 @@
                 }
             }};
 
-        // This listener monitors our camera session (i.e. our transition into and out of preview).
-        private CameraCaptureSession.StateListener mCameraPreviewStateListener =
-                new CameraCaptureSession.StateListener() {
+        // This callback monitors our camera session (i.e. our transition into and out of preview).
+        private CameraCaptureSession.StateCallback mCameraPreviewStateCallback =
+                new CameraCaptureSession.StateCallback() {
             @Override
             public void onConfigured(CameraCaptureSession session) {
                 mSession = session;
-                mCameraState.setState(AndroidCamera2StateHolder.CAMERA_PREVIEW_READY);
+                changeState(AndroidCamera2StateHolder.CAMERA_PREVIEW_READY);
             }
 
             @Override
@@ -724,49 +802,76 @@
                 }
             }};
 
-        // This listener monitors requested captures and notifies any relevant callbacks.
-        private CameraCaptureSession.CaptureListener mCameraFocusStateListener =
-                new CameraCaptureSession.CaptureListener() {
+        private abstract class CameraResultStateCallback
+                extends CameraCaptureSession.CaptureCallback {
+            public abstract void monitorControlStates(CaptureResult result);
+
+            public abstract void resetState();
+        }
+
+        // This callback monitors requested captures and notifies any relevant callbacks.
+        private CameraResultStateCallback mCameraResultStateCallback =
+                new CameraResultStateCallback() {
             private int mLastAfState = -1;
+            private long mLastAfFrameNumber = -1;
+            private long mLastAeFrameNumber = -1;
+
+            @Override
+            public void onCaptureProgressed(CameraCaptureSession session, CaptureRequest request,
+                                            CaptureResult result) {
+                monitorControlStates(result);
+            }
 
             @Override
             public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
                                            TotalCaptureResult result) {
+                monitorControlStates(result);
+            }
+
+            @Override
+            public void monitorControlStates(CaptureResult result) {
                 Integer afStateMaybe = result.get(CaptureResult.CONTROL_AF_STATE);
                 if (afStateMaybe != null) {
                     int afState = afStateMaybe;
-                    boolean afStateChanged = false;
-                    if (afState != mLastAfState) {
+                    // Since we handle both partial and total results for multiple frames here, we
+                    // might get the final callbacks for an earlier frame after receiving one or
+                    // more that correspond to the next one. To prevent our data from oscillating,
+                    // we never consider AF states that are older than the last one we've seen.
+                    if (result.getFrameNumber() > mLastAfFrameNumber) {
+                        boolean afStateChanged = afState != mLastAfState;
                         mLastAfState = afState;
-                        afStateChanged = true;
-                    }
+                        mLastAfFrameNumber = result.getFrameNumber();
 
-                    switch (afState) {
-                        case CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN:
-                        case CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED:
-                        case CaptureResult.CONTROL_AF_STATE_PASSIVE_UNFOCUSED: {
-                            if (afStateChanged && mPassiveAfCallback != null) {
-                                // A CameraAFMoveCallback is attached. If we just started to scan,
-                                // the motor is moving; otherwise, it has settled.
-                                mPassiveAfCallback.onAutoFocusMoving(
-                                        afState == CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN,
-                                        mCameraProxy);
+                        switch (afState) {
+                            case CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN:
+                            case CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED:
+                            case CaptureResult.CONTROL_AF_STATE_PASSIVE_UNFOCUSED: {
+                                if (afStateChanged && mPassiveAfCallback != null) {
+                                    // A CameraAFMoveCallback is attached. If we just started to
+                                    // scan, the motor is moving; otherwise, it has settled.
+                                    mPassiveAfCallback.onAutoFocusMoving(
+                                            afState == CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN,
+                                            mCameraProxy);
+                                }
+                                break;
                             }
-                            break;
-                        }
 
-                        case CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED:
-                        case CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED: {
-                            if (mOneshotAfCallback != null) {
-                                // A call to autoFocus() was just made to request a focus lock.
-                                // Notify the caller that the lens is now indefinitely fixed, and
-                                // report whether the image we're now stuck with is in focus.
-                                mOneshotAfCallback.onAutoFocus(
-                                        afState == CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED,
-                                        mCameraProxy);
-                                mOneshotAfCallback = null;
+                            case CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED:
+                            case CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED: {
+                                // This check must be made regardless of whether the focus state has
+                                // changed recently to avoid infinite waiting during autoFocus()
+                                // when the algorithm has already either converged or failed to.
+                                if (mOneshotAfCallback != null) {
+                                    // A call to autoFocus() was just made to request a focus lock.
+                                    // Notify the caller that the lens is now indefinitely fixed,
+                                    // and report whether the image we're stuck with is in focus.
+                                    mOneshotAfCallback.onAutoFocus(
+                                            afState == CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED,
+                                            mCameraProxy);
+                                    mOneshotAfCallback = null;
+                                }
+                                break;
                             }
-                            break;
                         }
                     }
                 }
@@ -774,36 +879,55 @@
                 Integer aeStateMaybe = result.get(CaptureResult.CONTROL_AE_STATE);
                 if (aeStateMaybe != null) {
                     int aeState = aeStateMaybe;
+                    // Since we handle both partial and total results for multiple frames here, we
+                    // might get the final callbacks for an earlier frame after receiving one or
+                    // more that correspond to the next one. To prevent our data from oscillating,
+                    // we never consider AE states that are older than the last one we've seen.
+                    if (result.getFrameNumber() > mLastAeFrameNumber) {
+                        mCurrentAeState = aeStateMaybe;
+                        mLastAeFrameNumber = result.getFrameNumber();
 
-                    switch (aeState) {
-                        case CaptureResult.CONTROL_AE_STATE_CONVERGED:
-                        case CaptureResult.CONTROL_AE_STATE_FLASH_REQUIRED:
-                        case CaptureResult.CONTROL_AE_STATE_LOCKED: {
-                            if (mOneshotCaptureCallback != null) {
-                                // A call to takePicture() was just made, and autoexposure converged
-                                // so it's time to initiate the capture!
-                                mCaptureReader.setOnImageAvailableListener(mOneshotCaptureCallback,
-                                        /*handler*/Camera2Handler.this);
-                                try {
-                                    mSession.capture(
-                                            mPersistentSettings.createRequest(mCamera,
-                                                    CameraDevice.TEMPLATE_STILL_CAPTURE,
-                                                    mCaptureReader.getSurface()),
+                        switch (aeState) {
+                            case CaptureResult.CONTROL_AE_STATE_CONVERGED:
+                            case CaptureResult.CONTROL_AE_STATE_FLASH_REQUIRED:
+                            case CaptureResult.CONTROL_AE_STATE_LOCKED: {
+                                // This check must be made regardless of whether the exposure state
+                                // has changed recently to avoid infinite waiting during
+                                // takePicture() when the algorithm has already converged.
+                                if (mOneshotCaptureCallback != null) {
+                                    // A call to takePicture() was just made, and autoexposure
+                                    // converged so it's time to initiate the capture!
+                                    mCaptureReader.setOnImageAvailableListener(
                                             /*listener*/mOneshotCaptureCallback,
                                             /*handler*/Camera2Handler.this);
-                                } catch (CameraAccessException ex) {
-                                    Log.e(TAG, "Unable to initiate capture", ex);
-                                } finally {
-                                    mOneshotCaptureCallback = null;
+                                    try {
+                                        mSession.capture(
+                                                mPersistentSettings.createRequest(mCamera,
+                                                        CameraDevice.TEMPLATE_STILL_CAPTURE,
+                                                        mCaptureReader.getSurface()),
+                                                /*callback*/mOneshotCaptureCallback,
+                                                /*handler*/Camera2Handler.this);
+                                    } catch (CameraAccessException ex) {
+                                        Log.e(TAG, "Unable to initiate capture", ex);
+                                    } finally {
+                                        mOneshotCaptureCallback = null;
+                                    }
                                 }
+                                break;
                             }
-                            break;
                         }
                     }
                 }
             }
 
             @Override
+            public void resetState() {
+                mLastAfState = -1;
+                mLastAfFrameNumber = -1;
+                mLastAeFrameNumber = -1;
+            }
+
+            @Override
             public void onCaptureFailed(CameraCaptureSession session, CaptureRequest request,
                                         CaptureFailure failure) {
                 Log.e(TAG, "Capture attempt failed with reason " + failure.getReason());
@@ -815,6 +939,8 @@
         private final CameraDevice mCamera;
         private final CameraDeviceInfo.Characteristics mCharacteristics;
         private final AndroidCamera2Capabilities mCapabilities;
+        private CameraSettings mLastSettings;
+        private boolean mShutterSoundEnabled;
 
         public AndroidCamera2ProxyImpl(int cameraIndex, CameraDevice camera,
                 CameraDeviceInfo.Characteristics characteristics,
@@ -823,6 +949,8 @@
             mCamera = camera;
             mCharacteristics = characteristics;
             mCapabilities = new AndroidCamera2Capabilities(properties);
+            mLastSettings = null;
+            mShutterSoundEnabled = true;
         }
 
         // TODO: Implement
@@ -848,6 +976,26 @@
             return mCapabilities;
         }
 
+        // FIXME: Unlock the sizes in stopPreview(), as per the corresponding
+        // explanation on the STOP_PREVIEW case in the handler.
+        @Override
+        public void setPreviewTexture(SurfaceTexture surfaceTexture) {
+            // Once the Surface has been selected, we configure the session and
+            // are no longer able to change the sizes.
+            getSettings().setSizesLocked(true);
+            super.setPreviewTexture(surfaceTexture);
+        }
+
+        // FIXME: Unlock the sizes in stopPreview(), as per the corresponding
+        // explanation on the STOP_PREVIEW case in the handler.
+        @Override
+        public void setPreviewTextureSync(SurfaceTexture surfaceTexture) {
+            // Once the Surface has been selected, we configure the session and
+            // are no longer able to change the sizes.
+            getSettings().setSizesLocked(true);
+            super.setPreviewTexture(surfaceTexture);
+        }
+
         // TODO: Implement
         @Override
         public void setPreviewDataCallback(Handler handler, CameraPreviewDataCallback cb) {}
@@ -915,7 +1063,6 @@
                 }});
         }
 
-        // TODO: Implement
         @Override
         public void takePicture(final Handler handler,
                                 final CameraShutterCallback shutter,
@@ -932,6 +1079,9 @@
                         handler.post(new Runnable() {
                             @Override
                             public void run() {
+                                if (mShutterSoundEnabled) {
+                                    mNoisemaker.play(MediaActionSound.SHUTTER_CLICK);
+                                }
                                 shutter.onShutter(AndroidCamera2ProxyImpl.this);
                             }});
                     }
@@ -955,8 +1105,9 @@
             mDispatchThread.runJob(new Runnable() {
                 @Override
                 public void run() {
-                    mCameraState.waitForStates(AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE |
-                            AndroidCamera2StateHolder.CAMERA_FOCUS_LOCKED);
+                    // Wait until PREVIEW_ACTIVE or better
+                    mCameraState.waitForStates(
+                            ~(AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE - 1));
                     mCameraHandler.obtainMessage(CameraActions.CAPTURE_PHOTO, picListener)
                             .sendToTarget();
                 }});
@@ -993,7 +1144,10 @@
 
         @Override
         public CameraSettings getSettings() {
-            return mCameraHandler.buildSettings(mCapabilities);
+            if (mLastSettings == null) {
+                mLastSettings = mCameraHandler.buildSettings(mCapabilities);
+            }
+            return mLastSettings;
         }
 
         @Override
@@ -1007,9 +1161,17 @@
                 return false;
             }
 
-            return applySettingsHelper(settings, AndroidCamera2StateHolder.CAMERA_UNCONFIGURED |
-                    AndroidCamera2StateHolder.CAMERA_CONFIGURED |
-                    AndroidCamera2StateHolder.CAMERA_PREVIEW_READY);
+            // Wait for any state that isn't OPENED
+            if (applySettingsHelper(settings, ~AndroidCamera2StateHolder.CAMERA_UNOPENED)) {
+                mLastSettings = settings;
+                return true;
+            }
+            return false;
+        }
+
+        @Override
+        public void enableShutterSound(boolean enable) {
+            mShutterSoundEnabled = enable;
         }
 
         // TODO: Implement
@@ -1036,19 +1198,22 @@
     private static class AndroidCamera2StateHolder extends CameraStateHolder {
         // Usage flow: openCamera() -> applySettings() -> setPreviewTexture() -> startPreview() ->
         //             autoFocus() -> takePicture()
+        // States are mutually exclusive, but must be separate bits so that they can be used with
+        // the StateHolder#waitForStates() and StateHolder#waitToAvoidStates() methods.
+        // Do not set the state to be a combination of these values!
         /* Camera states */
         /** No camera device is opened. */
-        public static final int CAMERA_UNOPENED = 1;
+        public static final int CAMERA_UNOPENED = 1 << 0;
         /** A camera is opened, but no settings have been provided. */
-        public static final int CAMERA_UNCONFIGURED = 2;
+        public static final int CAMERA_UNCONFIGURED = 1 << 1;
         /** The open camera has been configured by providing it with settings. */
-        public static final int CAMERA_CONFIGURED = 3;
+        public static final int CAMERA_CONFIGURED = 1 << 2;
         /** A capture session is ready to stream a preview, but still has no repeating request. */
-        public static final int CAMERA_PREVIEW_READY = 4;
+        public static final int CAMERA_PREVIEW_READY = 1 << 3;
         /** A preview is currently being streamed. */
-        public static final int CAMERA_PREVIEW_ACTIVE = 5;
+        public static final int CAMERA_PREVIEW_ACTIVE = 1 << 4;
         /** The lens is locked on a particular region. */
-        public static final int CAMERA_FOCUS_LOCKED = 6;
+        public static final int CAMERA_FOCUS_LOCKED = 1 << 5;
 
         public AndroidCamera2StateHolder() {
             this(CAMERA_UNOPENED);
@@ -1169,9 +1334,7 @@
 
             @Override
             public boolean canDisableShutterSound() {
-                // The new API doesn't support this operation, so don't encourage people to try it.
-                // TODO: What kind of assumptions have callers made about this result's meaning?
-                return false;
+                return true;
             }
 
             private static float[] convertRectToPoly(RectF rf) {
diff --git a/camera2/portability/src/com/android/ex/camera2/portability/AndroidCamera2Capabilities.java b/camera2/portability/src/com/android/ex/camera2/portability/AndroidCamera2Capabilities.java
index 51c1422..8001a37 100644
--- a/camera2/portability/src/com/android/ex/camera2/portability/AndroidCamera2Capabilities.java
+++ b/camera2/portability/src/com/android/ex/camera2/portability/AndroidCamera2Capabilities.java
@@ -81,7 +81,7 @@
         mMaxNumOfFacesSupported = p.get(STATISTICS_INFO_MAX_FACE_COUNT);
         mMaxNumOfMeteringArea = p.get(CONTROL_MAX_REGIONS_AE);
 
-        // TODO: Populate mMaxZoomRatio
+        mMaxZoomRatio = p.get(SCALER_AVAILABLE_MAX_DIGITAL_ZOOM);
         // TODO: Populate mHorizontalViewAngle
         // TODO: Populate mVerticalViewAngle
         // TODO: Populate mZoomRatioList
@@ -97,6 +97,10 @@
             mSupportedFeatures.add(Feature.METERING_AREA);
         }
 
+        if (mMaxZoomRatio > CameraCapabilities.ZOOM_RATIO_UNZOOMED) {
+            mSupportedFeatures.add(Feature.ZOOM);
+        }
+
         // TODO: Detect other features
     }
 
@@ -200,7 +204,6 @@
                 return SceneMode.CANDLELIGHT;
             case CONTROL_SCENE_MODE_FIREWORKS:
                 return SceneMode.FIREWORKS;
-            // TODO: We cannot support HDR
             case CONTROL_SCENE_MODE_LANDSCAPE:
                 return SceneMode.LANDSCAPE;
             case CONTROL_SCENE_MODE_NIGHT:
@@ -222,6 +225,11 @@
                 return SceneMode.THEATRE;
             // TODO: We cannot expose FACE_PRIORITY, or HIGH_SPEED_VIDEO
         }
+
+        if (sm == LegacyVendorTags.CONTROL_SCENE_MODE_HDR) {
+            return SceneMode.HDR;
+        }
+
         Log.w(TAG, "Unable to convert from API 2 scene mode: " + sm);
         return null;
     }
diff --git a/camera2/portability/src/com/android/ex/camera2/portability/AndroidCamera2Settings.java b/camera2/portability/src/com/android/ex/camera2/portability/AndroidCamera2Settings.java
index efa68e8..540d8df 100644
--- a/camera2/portability/src/com/android/ex/camera2/portability/AndroidCamera2Settings.java
+++ b/camera2/portability/src/com/android/ex/camera2/portability/AndroidCamera2Settings.java
@@ -18,10 +18,13 @@
 
 import static android.hardware.camera2.CaptureRequest.*;
 
+import android.graphics.Matrix;
 import android.graphics.Rect;
+import android.graphics.RectF;
 import android.hardware.camera2.CameraAccessException;
 import android.hardware.camera2.CameraDevice;
 import android.hardware.camera2.params.MeteringRectangle;
+import android.location.Location;
 import android.util.Range;
 
 import com.android.ex.camera2.portability.CameraCapabilities.FlashMode;
@@ -41,8 +44,13 @@
     private static final Log.Tag TAG = new Log.Tag("AndCam2Set");
 
     private final Builder mTemplateSettings;
-    private final Rect mActiveArray;
     private final Camera2RequestSettingsSet mRequestSettings;
+    /** Sensor's active array bounds. */
+    private final Rect mActiveArray;
+    /** Crop rectangle for digital zoom (measured WRT the active array). */
+    private final Rect mCropRectangle;
+    /** Bounds of visible preview portion (measured WRT the active array). */
+    private Rect mVisiblePreviewRectangle;
 
     /**
      * Create a settings representation that answers queries of unspecified
@@ -56,19 +64,33 @@
      * their effective values when submitting a capture request will be those of
      * the template that is provided to the camera framework at that time.</p>
      *
-     * @param camera Device from which to draw default settings.
+     * @param camera Device from which to draw default settings
+     *               (non-{@code null}).
      * @param template Specific template to use for the defaults.
-     * @param activeArray Boundary coordinates of the sensor's active array.
+     * @param activeArray Boundary coordinates of the sensor's active array
+     *                    (non-{@code null}).
      * @param preview Dimensions of preview streams.
      * @param photo Dimensions of captured images.
      *
+     * @throws IllegalArgumentException If {@code camera} or {@code activeArray}
+     *                                  is {@code null}.
      * @throws CameraAccessException Upon internal framework/driver failure.
      */
     public AndroidCamera2Settings(CameraDevice camera, int template, Rect activeArray,
                                   Size preview, Size photo) throws CameraAccessException {
+        if (camera == null) {
+            throw new NullPointerException("camera must not be null");
+        }
+        if (activeArray == null) {
+            throw new NullPointerException("activeArray must not be null");
+        }
+
         mTemplateSettings = camera.createCaptureRequest(template);
-        mActiveArray = activeArray;
         mRequestSettings = new Camera2RequestSettingsSet();
+        mActiveArray = activeArray;
+        mCropRectangle = new Rect(0, 0, activeArray.width(), activeArray.height());
+
+        mSizesLocked = false;
 
         Range<Integer> previewFpsRange = mTemplateSettings.get(CONTROL_AE_TARGET_FPS_RANGE);
         if (previewFpsRange != null) {
@@ -79,8 +101,8 @@
         setPhotoSize(photo);
         mJpegCompressQuality = queryTemplateDefaultOrMakeOneUp(JPEG_QUALITY, (byte) 0);
         // TODO: mCurrentPhotoFormat
-        // TODO: mCurrentZoomRatio
-        mCurrentZoomRatio = 1.0f;
+        // NB: We're assuming that templates won't be zoomed in by default.
+        mCurrentZoomRatio = CameraCapabilities.ZOOM_RATIO_UNZOOMED;
         // TODO: mCurrentZoomIndex
         mExposureCompensationIndex =
                 queryTemplateDefaultOrMakeOneUp(CONTROL_AE_EXPOSURE_COMPENSATION, 0);
@@ -116,8 +138,9 @@
     public AndroidCamera2Settings(AndroidCamera2Settings other) {
         super(other);
         mTemplateSettings = other.mTemplateSettings;
-        mActiveArray = other.mActiveArray;
         mRequestSettings = new Camera2RequestSettingsSet(other.mRequestSettings);
+        mActiveArray = other.mActiveArray;
+        mCropRectangle = new Rect(other.mCropRectangle);
     }
 
     @Override
@@ -159,13 +182,31 @@
         return null;
     }
 
+    @Override
+    public void setZoomRatio(float ratio) {
+        super.setZoomRatio(ratio);
+
+        // Compute the crop rectangle to be passed to the framework
+        mCropRectangle.set(0, 0,
+                toIntConstrained(
+                        mActiveArray.width() / mCurrentZoomRatio, 0, mActiveArray.width()),
+                toIntConstrained(
+                        mActiveArray.height() / mCurrentZoomRatio, 0, mActiveArray.height()));
+        mCropRectangle.offsetTo((mActiveArray.width() - mCropRectangle.width()) / 2,
+                (mActiveArray.height() - mCropRectangle.height()) / 2);
+
+        // Compute the effective crop rectangle to be used for computing focus/metering coordinates
+        mVisiblePreviewRectangle =
+                effectiveCropRectFromRequested(mCropRectangle, mCurrentPreviewSize);
+    }
+
     private boolean matchesTemplateDefault(Key<?> setting) {
         if (setting == CONTROL_AE_REGIONS) {
             return mMeteringAreas.size() == 0;
         } else if (setting == CONTROL_AF_REGIONS) {
             return mFocusAreas.size() == 0;
         } else if (setting == CONTROL_AE_TARGET_FPS_RANGE) {
-            Range defaultFpsRange = mTemplateSettings.get(CONTROL_AE_TARGET_FPS_RANGE);
+            Range<Integer> defaultFpsRange = mTemplateSettings.get(CONTROL_AE_TARGET_FPS_RANGE);
             return (mPreviewFpsRangeMin == 0 && mPreviewFpsRangeMax == 0) ||
                     (defaultFpsRange != null && mPreviewFpsRangeMin == defaultFpsRange.getLower() &&
                             mPreviewFpsRangeMax == defaultFpsRange.getUpper());
@@ -213,7 +254,7 @@
         // TODO: mCurrentPreviewFormat
         updateRequestSettingOrForceToDefault(JPEG_QUALITY, mJpegCompressQuality);
         // TODO: mCurrentPhotoFormat
-        // TODO: mCurrentZoomRatio
+        mRequestSettings.set(SCALER_CROP_REGION, mCropRectangle);
         // TODO: mCurrentZoomIndex
         updateRequestSettingOrForceToDefault(CONTROL_AE_EXPOSURE_COMPENSATION,
                 mExposureCompensationIndex);
@@ -231,7 +272,7 @@
         updateRequestSettingOrForceToDefault(CONTROL_AE_LOCK, mAutoExposureLocked);
         updateRequestSettingOrForceToDefault(CONTROL_AWB_LOCK, mAutoWhiteBalanceLocked);
         // TODO: mRecordingHintEnabled
-        // TODO: mGpsData
+        updateRequestGpsData();
         updateRequestSettingOrForceToDefault(JPEG_THUMBNAIL_SIZE,
                 new android.util.Size(
                         mExifThumbnailSize.width(), mExifThumbnailSize.height()));
@@ -243,25 +284,25 @@
             List<android.hardware.Camera.Area> reference) {
         MeteringRectangle[] transformed = null;
         if (reference.size() > 0) {
-
             transformed = new MeteringRectangle[reference.size()];
             for (int index = 0; index < reference.size(); ++index) {
                 android.hardware.Camera.Area source = reference.get(index);
                 Rect rectangle = source.rect;
 
                 // Old API coordinates were [-1000,1000]; new ones are [0,ACTIVE_ARRAY_SIZE).
+                // We're also going from preview image--relative to sensor active array--relative.
                 double oldLeft = (rectangle.left + 1000) / 2000.0;
                 double oldTop = (rectangle.top + 1000) / 2000.0;
                 double oldRight = (rectangle.right + 1000) / 2000.0;
                 double oldBottom = (rectangle.bottom + 1000) / 2000.0;
-                int left = toIntConstrained( mActiveArray.width() * oldLeft + mActiveArray.left,
-                        0, mActiveArray.width() - 1);
-                int top = toIntConstrained( mActiveArray.height() * oldTop + mActiveArray.top,
-                        0, mActiveArray.height() - 1);
-                int right = toIntConstrained( mActiveArray.width() * oldRight + mActiveArray.left,
-                        0, mActiveArray.width() - 1);
-                int bottom = toIntConstrained( mActiveArray.height() * oldBottom + mActiveArray.top,
-                        0, mActiveArray.height() - 1);
+                int left = mCropRectangle.left + toIntConstrained(
+                        mCropRectangle.width() * oldLeft, 0, mCropRectangle.width() - 1);
+                int top = mCropRectangle.top + toIntConstrained(
+                        mCropRectangle.height() * oldTop, 0, mCropRectangle.height() - 1);
+                int right = mCropRectangle.left + toIntConstrained(
+                        mCropRectangle.width() * oldRight, 0, mCropRectangle.width() - 1);
+                int bottom = mCropRectangle.top + toIntConstrained(
+                        mCropRectangle.height() * oldBottom, 0, mCropRectangle.height() - 1);
                 transformed[index] = new MeteringRectangle(left, top, right - left, bottom - top,
                         source.weight);
             }
@@ -378,7 +419,10 @@
                     mode = CONTROL_SCENE_MODE_FIREWORKS;
                     break;
                 }
-                // TODO: We cannot support HDR
+                case HDR: {
+                    mode = LegacyVendorTags.CONTROL_SCENE_MODE_HDR;
+                    break;
+                }
                 case LANDSCAPE: {
                     mode = CONTROL_SCENE_MODE_LANDSCAPE;
                     break;
@@ -469,4 +513,65 @@
         }
         mRequestSettings.set(CONTROL_AWB_MODE, mode);
     }
+
+    private void updateRequestGpsData() {
+        if (mGpsData == null || mGpsData.processingMethod == null) {
+            // It's a hack since we always use GPS time stamp but does
+            // not use other fields sometimes. Setting processing
+            // method to null means the other fields should not be used.
+            mRequestSettings.set(JPEG_GPS_LOCATION, null);
+        } else {
+            Location location = new Location(mGpsData.processingMethod);
+            location.setTime(mGpsData.timeStamp);
+            location.setAltitude(mGpsData.altitude);
+            location.setLatitude(mGpsData.latitude);
+            location.setLongitude(mGpsData.longitude);
+            mRequestSettings.set(JPEG_GPS_LOCATION, location);
+        }
+    }
+
+    /**
+     * Calculate the effective crop rectangle for this preview viewport;
+     * assumes the preview is centered to the sensor and scaled to fit across one of the dimensions
+     * without skewing.
+     *
+     * <p>Assumes the zoom level of the provided desired crop rectangle.</p>
+     *
+     * @param requestedCrop Desired crop rectangle, in active array space.
+     * @param previewSize Size of the preview buffer render target, in pixels (not in sensor space).
+     * @return A rectangle that serves as the preview stream's effective crop region (unzoomed), in
+     *          sensor space.
+     *
+     * @throws NullPointerException
+     *          If any of the args were {@code null}.
+     */
+    private static Rect effectiveCropRectFromRequested(Rect requestedCrop, Size previewSize) {
+        float aspectRatioArray = requestedCrop.width() * 1.0f / requestedCrop.height();
+        float aspectRatioPreview = previewSize.width() * 1.0f / previewSize.height();
+
+        float cropHeight, cropWidth;
+        if (aspectRatioPreview < aspectRatioArray) {
+            // The new width must be smaller than the height, so scale the width by AR
+            cropHeight = requestedCrop.height();
+            cropWidth = cropHeight * aspectRatioPreview;
+        } else {
+            // The new height must be smaller (or equal) than the width, so scale the height by AR
+            cropWidth = requestedCrop.width();
+            cropHeight = cropWidth / aspectRatioPreview;
+        }
+
+        Matrix translateMatrix = new Matrix();
+        RectF cropRect = new RectF(/*left*/0, /*top*/0, cropWidth, cropHeight);
+
+        // Now center the crop rectangle so its center is in the center of the active array
+        translateMatrix.setTranslate(requestedCrop.exactCenterX(), requestedCrop.exactCenterY());
+        translateMatrix.postTranslate(-cropRect.centerX(), -cropRect.centerY());
+
+        translateMatrix.mapRect(/*inout*/cropRect);
+
+        // Round the rect corners towards the nearest integer values
+        Rect result = new Rect();
+        cropRect.roundOut(result);
+        return result;
+    }
 }
diff --git a/camera2/portability/src/com/android/ex/camera2/portability/AndroidCameraAgentImpl.java b/camera2/portability/src/com/android/ex/camera2/portability/AndroidCameraAgentImpl.java
index a9aba37..949ac62 100644
--- a/camera2/portability/src/com/android/ex/camera2/portability/AndroidCameraAgentImpl.java
+++ b/camera2/portability/src/com/android/ex/camera2/portability/AndroidCameraAgentImpl.java
@@ -38,6 +38,8 @@
 import com.android.ex.camera2.portability.debug.Log;
 
 import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
 import java.util.StringTokenizer;
 
 /**
@@ -402,6 +404,7 @@
                         break;
                     }
 
+                    // TODO: Lock the CameraSettings object's sizes
                     case CameraActions.SET_PREVIEW_TEXTURE_ASYNC: {
                         setPreviewTexture(msg.obj);
                         break;
@@ -426,6 +429,7 @@
                         break;
                     }
 
+                    // TODO: Unlock the CameraSettings object's sizes
                     case CameraActions.STOP_PREVIEW: {
                         mCamera.stopPreview();
                         break;
@@ -600,8 +604,8 @@
             parameters.setPreviewFormat(settings.getCurrentPreviewFormat());
             parameters.setJpegQuality(settings.getPhotoJpegCompressionQuality());
             if (mCapabilities.supports(CameraCapabilities.Feature.ZOOM)) {
-                // Should use settings.getCurrentZoomRatio() instead here.
-                parameters.setZoom(settings.getCurrentZoomIndex());
+                parameters.setZoom(zoomRatioToIndex(settings.getCurrentZoomRatio(),
+                        parameters.getZoomRatios()));
             }
             parameters.setExposureCompensation(settings.getExposureCompensationIndex());
             if (mCapabilities.supports(CameraCapabilities.Feature.AUTO_EXPOSURE_LOCK)) {
@@ -614,11 +618,15 @@
             if (mCapabilities.supports(CameraCapabilities.Feature.FOCUS_AREA)) {
                 if (settings.getFocusAreas().size() != 0) {
                     parameters.setFocusAreas(settings.getFocusAreas());
+                } else {
+                    parameters.setFocusAreas(null);
                 }
             }
             if (mCapabilities.supports(CameraCapabilities.Feature.METERING_AREA)) {
                 if (settings.getMeteringAreas().size() != 0) {
                     parameters.setMeteringAreas(settings.getMeteringAreas());
+                } else {
+                    parameters.setMeteringAreas(null);
                 }
             }
             if (settings.getCurrentFlashMode() != CameraCapabilities.FlashMode.NO_FLASH) {
@@ -652,6 +660,29 @@
             }
 
         }
+
+        /**
+         * @param ratio Desired zoom ratio, in [1.0f,+Inf).
+         * @param percentages Available zoom ratios, as percentages.
+         * @return Index of the closest corresponding ratio, rounded up toward
+         *         that of the maximum available ratio.
+         */
+        private int zoomRatioToIndex(float ratio, List<Integer> percentages) {
+            int percent = (int) (ratio * AndroidCameraCapabilities.ZOOM_MULTIPLIER);
+            int index = Collections.binarySearch(percentages, percent);
+            if (index >= 0) {
+                // Found the desired ratio in the supported list
+                return index;
+            } else {
+                // Didn't find an exact match. Where would it have been?
+                index = -(index + 1);
+                if (index == percentages.size()) {
+                    // Put it back in bounds by setting to the maximum allowable zoom
+                    --index;
+                }
+                return index;
+            }
+        }
     }
 
     /**
diff --git a/camera2/portability/src/com/android/ex/camera2/portability/AndroidCameraCapabilities.java b/camera2/portability/src/com/android/ex/camera2/portability/AndroidCameraCapabilities.java
index acff9c6..84b44e6 100644
--- a/camera2/portability/src/com/android/ex/camera2/portability/AndroidCameraCapabilities.java
+++ b/camera2/portability/src/com/android/ex/camera2/portability/AndroidCameraCapabilities.java
@@ -31,6 +31,9 @@
 
     private static Log.Tag TAG = new Log.Tag("AndCamCapabs");
 
+    /** Conversion from ratios to percentages. */
+    public static final float ZOOM_MULTIPLIER = 100f;
+
     private FpsComparator mFpsComparator = new FpsComparator();
     private SizeComparator mSizeComparator = new SizeComparator();
 
@@ -44,9 +47,7 @@
         mPreferredPreviewSizeForVideo = new Size(p.getPreferredPreviewSizeForVideo());
         mSupportedPreviewFormats.addAll(p.getSupportedPreviewFormats());
         mSupportedPhotoFormats.addAll(p.getSupportedPictureFormats());
-        mMaxZoomIndex = p.getMaxZoom();
-        mZoomRatioList.addAll(p.getZoomRatios());
-        mMaxZoomRatio = mZoomRatioList.get(mMaxZoomIndex);
+        mMaxZoomRatio = p.getZoomRatios().get(p.getMaxZoom()) / ZOOM_MULTIPLIER;
         mHorizontalViewAngle = p.getHorizontalViewAngle();
         mVerticalViewAngle = p.getVerticalViewAngle();
         buildPreviewFpsRange(p);
diff --git a/camera2/portability/src/com/android/ex/camera2/portability/AndroidCameraSettings.java b/camera2/portability/src/com/android/ex/camera2/portability/AndroidCameraSettings.java
index ceab7fe..ee69b54 100644
--- a/camera2/portability/src/com/android/ex/camera2/portability/AndroidCameraSettings.java
+++ b/camera2/portability/src/com/android/ex/camera2/portability/AndroidCameraSettings.java
@@ -28,6 +28,8 @@
     public AndroidCameraSettings(CameraCapabilities capabilities, Camera.Parameters params) {
         CameraCapabilities.Stringifier stringifier = capabilities.getStringifier();
 
+        setSizesLocked(false);
+
         // Preview
         Camera.Size paramPreviewSize = params.getPreviewSize();
         setPreviewSize(new Size(paramPreviewSize.width, paramPreviewSize.height));
@@ -41,10 +43,8 @@
         // Capture: Focus, flash, zoom, exposure, scene mode.
         if (capabilities.supports(CameraCapabilities.Feature.ZOOM)) {
             setZoomRatio(params.getZoomRatios().get(params.getZoom()) / 100f);
-            setZoomIndex(params.getZoom());
         } else {
-            setZoomRatio(1.0f);
-            setZoomIndex(0);
+            setZoomRatio(CameraCapabilities.ZOOM_RATIO_UNZOOMED);
         }
         setExposureCompensationIndex(params.getExposureCompensation());
         setFlashMode(stringifier.flashModeFromString(params.getFlashMode()));
diff --git a/camera2/portability/src/com/android/ex/camera2/portability/CameraAgent.java b/camera2/portability/src/com/android/ex/camera2/portability/CameraAgent.java
index dd4f77c..b624b47 100644
--- a/camera2/portability/src/com/android/ex/camera2/portability/CameraAgent.java
+++ b/camera2/portability/src/com/android/ex/camera2/portability/CameraAgent.java
@@ -436,8 +436,24 @@
         /**
          * Sets the {@link android.graphics.SurfaceTexture} for preview.
          *
+         * <p>Note that, once this operation has been performed, it is no longer
+         * possible to change the preview or photo sizes in the
+         * {@link CameraSettings} instance for this camera, and the mutators for
+         * these fields are allowed to ignore all further invocations until the
+         * preview is stopped with {@link #stopPreview}.</p>
+         *
          * @param surfaceTexture The {@link SurfaceTexture} for preview.
+         *
+         * @see CameraSettings#setPhotoSize
+         * @see CameraSettings#setPreviewSize
          */
+        // XXX: Despite the above documentation about locking the sizes, the API
+        // 1 implementation doesn't currently enforce this at all, although the
+        // Camera class warns that preview sizes shouldn't be changed while a
+        // preview is running. Furthermore, the API 2 implementation doesn't yet
+        // unlock the sizes when stopPreview() is invoked (see related FIXME on
+        // the STOP_PREVIEW case in its handler; in the meantime, changing API 2
+        // sizes would require closing and reopening the camera.
         public void setPreviewTexture(final SurfaceTexture surfaceTexture) {
             getDispatchThread().runJob(new Runnable() {
                 @Override
@@ -452,7 +468,15 @@
          * Blocks until a {@link android.graphics.SurfaceTexture} has been set
          * for preview.
          *
+         * <p>Note that, once this operation has been performed, it is no longer
+         * possible to change the preview or photo sizes in the
+         * {@link CameraSettings} instance for this camera, and the mutators for
+         * these fields are allowed to ignore all further invocations.</p>
+         *
          * @param surfaceTexture The {@link SurfaceTexture} for preview.
+         *
+         * @see CameraSettings#setPhotoSize
+         * @see CameraSettings#setPreviewSize
          */
         public void setPreviewTextureSync(final SurfaceTexture surfaceTexture) {
             final WaitDoneBundle bundle = new WaitDoneBundle();
@@ -732,10 +756,11 @@
         protected boolean applySettingsHelper(CameraSettings settings,
                                               final int statesToAwait) {
             if (settings == null) {
-                Log.v(TAG, "null parameters in applySettings()");
+                Log.v(TAG, "null argument in applySettings()");
                 return false;
             }
             if (!getCapabilities().supports(settings)) {
+                Log.w(TAG, "Unsupported settings in applySettings()");
                 return false;
             }
 
diff --git a/camera2/portability/src/com/android/ex/camera2/portability/CameraCapabilities.java b/camera2/portability/src/com/android/ex/camera2/portability/CameraCapabilities.java
index 6a4c72c..60c8cb2 100644
--- a/camera2/portability/src/com/android/ex/camera2/portability/CameraCapabilities.java
+++ b/camera2/portability/src/com/android/ex/camera2/portability/CameraCapabilities.java
@@ -36,6 +36,9 @@
 
     private static Log.Tag TAG = new Log.Tag("CamCapabs");
 
+    /** Zoom ratio used for seeing sensor's full field of view. */
+    protected static final float ZOOM_RATIO_UNZOOMED = 1.0f;
+
     /* All internal states are declared final and should be thread-safe. */
 
     protected final ArrayList<int[]> mSupportedPreviewFpsRange = new ArrayList<int[]>();
@@ -57,12 +60,10 @@
     protected int mMaxNumOfFacesSupported;
     protected int mMaxNumOfFocusAreas;
     protected int mMaxNumOfMeteringArea;
-    protected int mMaxZoomRatio;
+    protected float mMaxZoomRatio;
     protected float mHorizontalViewAngle;
     protected float mVerticalViewAngle;
     private final Stringifier mStringifier;
-    protected final ArrayList<Integer> mZoomRatioList = new ArrayList<Integer>();
-    protected int mMaxZoomIndex;
 
     /**
      * Focus modes.
@@ -183,7 +184,7 @@
          * Capture a scene using high dynamic range imaging techniques.
          * @see {@link android.hardware.Camera.Parameters#SCENE_MODE_HDR}.
          */
-        // TODO: Unsupported on API 2
+        // Note: Supported as a vendor tag on the Camera2 API for some LEGACY devices.
         HDR,
         /**
          * Take pictures on distant objects.
@@ -488,8 +489,6 @@
         mMaxNumOfFacesSupported = src.mMaxNumOfFacesSupported;
         mMaxNumOfFocusAreas = src.mMaxNumOfFocusAreas;
         mMaxNumOfMeteringArea = src.mMaxNumOfMeteringArea;
-        mMaxZoomIndex = src.mMaxZoomIndex;
-        mZoomRatioList.addAll(src.mZoomRatioList);
         mMaxZoomRatio = src.mMaxZoomRatio;
         mHorizontalViewAngle = src.mHorizontalViewAngle;
         mVerticalViewAngle = src.mVerticalViewAngle;
@@ -635,17 +634,6 @@
         return mMaxZoomRatio;
     }
 
-    // We'll replace these old style methods with new ones.
-    @Deprecated
-    public int getMaxZoomIndex() {
-        return mMaxZoomIndex;
-    }
-
-    @Deprecated
-    public List<Integer> getZoomRatioList() {
-        return new ArrayList<Integer>(mZoomRatioList);
-    }
-
     /**
      * @return The min exposure compensation index. The EV is the compensation
      * index multiplied by the step value. If unsupported, both this method and
@@ -689,17 +677,15 @@
 
     private boolean zoomCheck(final CameraSettings settings) {
         final float ratio = settings.getCurrentZoomRatio();
-        final int index = settings.getCurrentZoomIndex();
         if (!supports(Feature.ZOOM)) {
-            if (ratio != 1.0f || index != 0) {
+            if (ratio != ZOOM_RATIO_UNZOOMED) {
                 Log.v(TAG, "Zoom is not supported");
                 return false;
             }
         } else {
-            if (settings.getCurrentZoomRatio() > getMaxZoomRatio() ||
-                    index > getMaxZoomIndex()) {
+            if (settings.getCurrentZoomRatio() > getMaxZoomRatio()) {
                 Log.v(TAG, "Zoom ratio is not supported: ratio = " +
-                        settings.getCurrentZoomRatio() + ", index = " + index);
+                        settings.getCurrentZoomRatio());
                 return false;
             }
         }
@@ -720,9 +706,16 @@
     private boolean focusCheck(final CameraSettings settings) {
         FocusMode focusMode = settings.getCurrentFocusMode();
         if (!supports(focusMode)) {
-            Log.v(TAG,
-                    "Focus mode not supported:" + (focusMode != null ? focusMode.name() : "null"));
-            return false;
+            if (supports(FocusMode.FIXED)) {
+                // Workaround for devices whose templates define defaults they don't really support
+                // TODO: Remove workaround (b/17177436)
+                Log.w(TAG, "Focus mode not supported... trying FIXED");
+                settings.setFocusMode(FocusMode.FIXED);
+            } else {
+                Log.v(TAG, "Focus mode not supported:" +
+                        (focusMode != null ? focusMode.name() : "null"));
+                return false;
+            }
         }
         return true;
     }
diff --git a/camera2/portability/src/com/android/ex/camera2/portability/CameraSettings.java b/camera2/portability/src/com/android/ex/camera2/portability/CameraSettings.java
index 26d0f85..87e9adf 100644
--- a/camera2/portability/src/com/android/ex/camera2/portability/CameraSettings.java
+++ b/camera2/portability/src/com/android/ex/camera2/portability/CameraSettings.java
@@ -38,6 +38,7 @@
     protected final Map<String, String> mGeneralSetting = new TreeMap<>();
     protected final List<Camera.Area> mMeteringAreas = new ArrayList<>();
     protected final List<Camera.Area> mFocusAreas = new ArrayList<>();
+    protected boolean mSizesLocked;
     protected int mPreviewFpsRangeMin;
     protected int mPreviewFpsRangeMax;
     protected int mPreviewFrameRate;
@@ -47,7 +48,6 @@
     protected byte mJpegCompressQuality;
     protected int mCurrentPhotoFormat;
     protected float mCurrentZoomRatio;
-    protected int mCurrentZoomIndex;
     protected int mExposureCompensationIndex;
     protected CameraCapabilities.FlashMode mCurrentFlashMode;
     protected CameraCapabilities.FocusMode mCurrentFocusMode;
@@ -73,9 +73,20 @@
         public final long timeStamp;
         public final String processingMethod;
 
-        /** Constructor. */
+        /**
+         * Construct what may or may not actually represent a location,
+         * depending on the value of {@code processingMethod}.
+         *
+         * <p>Setting {@code processingMethod} to {@code null} means that
+         * {@code latitude}, {@code longitude}, and {@code altitude} will be
+         * completely ignored.</p>
+         */
         public GpsData(double latitude, double longitude, double altitude, long timeStamp,
                 String processingMethod) {
+            if (processingMethod == null &&
+                    (latitude != 0.0 || longitude != 0.0 || altitude != 0.0)) {
+                Log.w(TAG, "GpsData's nonzero data will be ignored due to null processingMethod");
+            }
             this.latitude = latitude;
             this.longitude = longitude;
             this.altitude = altitude;
@@ -106,6 +117,7 @@
         mGeneralSetting.putAll(src.mGeneralSetting);
         mMeteringAreas.addAll(src.mMeteringAreas);
         mFocusAreas.addAll(src.mFocusAreas);
+        mSizesLocked = src.mSizesLocked;
         mPreviewFpsRangeMin = src.mPreviewFpsRangeMin;
         mPreviewFpsRangeMax = src.mPreviewFpsRangeMax;
         mPreviewFrameRate = src.mPreviewFrameRate;
@@ -117,7 +129,6 @@
         mJpegCompressQuality = src.mJpegCompressQuality;
         mCurrentPhotoFormat = src.mCurrentPhotoFormat;
         mCurrentZoomRatio = src.mCurrentZoomRatio;
-        mCurrentZoomIndex = src.mCurrentZoomIndex;
         mExposureCompensationIndex = src.mExposureCompensationIndex;
         mCurrentFlashMode = src.mCurrentFlashMode;
         mCurrentFocusMode = src.mCurrentFocusMode;
@@ -142,6 +153,19 @@
         mGeneralSetting.put(key, value);
     }
 
+    /**
+     * Changes whether classes outside this class are allowed to set the preview
+     * and photo capture sizes.
+     *
+     * @param locked Whether to prevent changes to these fields.
+     *
+     * @see #setPhotoSize
+     * @see #setPreviewSize
+     */
+    /*package*/ void setSizesLocked(boolean locked) {
+        mSizesLocked = locked;
+    }
+
     /**  Preview **/
 
     /**
@@ -203,9 +227,16 @@
 
     /**
      * @param previewSize The size to use for preview.
+     * @return Whether the operation was allowed (i.e. the sizes are unlocked).
      */
-    public void setPreviewSize(Size previewSize) {
+    public boolean setPreviewSize(Size previewSize) {
+        if (mSizesLocked) {
+            Log.w(TAG, "Attempt to change preview size while locked");
+            return false;
+        }
+
         mCurrentPreviewSize = new Size(previewSize);
+        return true;
     }
 
     /**
@@ -236,12 +267,17 @@
     }
 
     /**
-     * Sets the size for the photo.
-     *
-     * @param photoSize The photo size.
+     * @param photoSize The size to use for preview.
+     * @return Whether the operation was allowed (i.e. the sizes are unlocked).
      */
-    public void setPhotoSize(Size photoSize) {
+    public boolean setPhotoSize(Size photoSize) {
+        if (mSizesLocked) {
+            Log.w(TAG, "Attempt to change photo size while locked");
+            return false;
+        }
+
         mCurrentPhotoSize = new Size(photoSize);
+        return true;
     }
 
     /**
@@ -301,16 +337,6 @@
         mCurrentZoomRatio = ratio;
     }
 
-    @Deprecated
-    public int getCurrentZoomIndex() {
-        return mCurrentZoomIndex;
-    }
-
-    @Deprecated
-    public void setZoomIndex(int index) {
-        mCurrentZoomIndex = index;
-    }
-
     /** Exposure **/
 
     public void setExposureCompensationIndex(int index) {
@@ -332,6 +358,14 @@
         return mAutoExposureLocked;
     }
 
+    /**
+     * @param areas The areas for autoexposure. The coordinate system has domain
+     *              and range [-1000,1000], measured relative to the visible
+     *              preview image, with orientation matching that of the sensor.
+     *              This means the coordinates must be transformed to account
+     *              for the devices rotation---but not the zoom level---before
+     *              being passed into this method.
+     */
     public void setMeteringAreas(List<Camera.Area> areas) {
         mMeteringAreas.clear();
         if (areas != null) {
@@ -371,7 +405,12 @@
     }
 
     /**
-     * @param areas The areas to focus.
+     * @param areas The areas to focus. The coordinate system has domain and
+     *              range [-1000,1000], measured relative to the visible preview
+     *              image, with orientation matching that of the sensor. This
+     *              means the coordinates must be transformed to account for
+     *              the devices rotation---but not the zoom level---before being
+     *              passed into this method.
      */
     public void setFocusAreas(List<Camera.Area> areas) {
         mFocusAreas.clear();
diff --git a/camera2/portability/src/com/android/ex/camera2/portability/LegacyVendorTags.java b/camera2/portability/src/com/android/ex/camera2/portability/LegacyVendorTags.java
new file mode 100644
index 0000000..7eb5c33
--- /dev/null
+++ b/camera2/portability/src/com/android/ex/camera2/portability/LegacyVendorTags.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2014 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.camera2.portability;
+
+import android.hardware.camera2.CameraCharacteristics;
+import android.util.Log;
+
+import java.lang.ExceptionInInitializerError;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+/**
+ * Vendor tag declarations for the Legacy Camera2 API implementation.
+ */
+public class LegacyVendorTags {
+
+    private static final String TAG = "LegacyVendorTags";
+
+    /**
+     * Hidden enum for scene modes supported only by the Camera1 API.
+     */
+    public static final int CONTROL_SCENE_MODE_HDR;
+
+    static {
+        int tempSceneMode = -1;
+        try {
+            tempSceneMode =
+                    Class.forName("android.hardware.camera2.CameraCharacteristics").
+                            getField("CONTROL_SCENE_MODE_HDR").getInt(null);
+        } catch (Exception e) {
+            Log.e(TAG, "Error while reflecting on SCENE_MODE_HDR enum, HDR will not be available: "
+                    + e);
+        } finally {
+            CONTROL_SCENE_MODE_HDR = tempSceneMode;
+        }
+    }
+
+    private LegacyVendorTags() {
+        throw new AssertionError();
+    }
+}
\ No newline at end of file
diff --git a/camera2/portability/tests/src/com/android/ex/camera2/portability/Camera2PortabilityTest.java b/camera2/portability/tests/src/com/android/ex/camera2/portability/Camera2PortabilityTest.java
index 034fac7..1f340fd 100644
--- a/camera2/portability/tests/src/com/android/ex/camera2/portability/Camera2PortabilityTest.java
+++ b/camera2/portability/tests/src/com/android/ex/camera2/portability/Camera2PortabilityTest.java
@@ -21,6 +21,7 @@
 import static org.junit.Assert.fail;
 
 import android.content.Context;
+import android.graphics.Rect;
 import android.hardware.camera2.CameraAccessException;
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CameraDevice;
@@ -40,6 +41,11 @@
 import java.lang.reflect.ParameterizedType;
 
 public class Camera2PortabilityTest extends Camera2DeviceTester {
+    /**
+     * Ensure that applying {@code Stringifier#.*FromString()} reverses
+     * {@link Stringifier#stringify} for {@link FocusMode}, {@link FlashMode},
+     * {@link SceneMode}, and {@link WhiteBalance}.
+     */
     @Test
     public void cameraCapabilitiesStringifier() {
         Stringifier strfy = new Stringifier();
@@ -57,6 +63,11 @@
         }
     }
 
+    /**
+     * Ensure that {@code Stringifier#.*FromString()} default to the correct
+     * {@link FocusMode}, {@link FlashMode}, {@link SceneMode}, and
+     * {@link WhiteBalance} when given a {@code null}.
+     */
     @Test
     public void cameraCapabilitiesStringifierNull() {
         Stringifier strfy = new Stringifier();
@@ -66,6 +77,11 @@
         assertEquals(strfy.whiteBalanceFromString(null), WhiteBalance.AUTO);
     }
 
+    /**
+     * Ensure that {@code Stringifier#.*FromString()} default to the correct
+     * {@link FocusMode}, {@link FlashMode}, {@link SceneMode}, and
+     * {@link WhiteBalance} when given an unrecognized string.
+     */
     @Test
     public void cameraCapabilitiesStringifierInvalid() {
         Stringifier strfy = new Stringifier();
@@ -86,10 +102,19 @@
         assertEquals(apiVal, setts.getRequestSettings().get(apiKey));
     }
 
+    /**
+     * Ensure that {@link AndroidCamera2Settings} correctly translates its
+     * {@code FocusMode}, {@code SceneMode}, and {@code WhiteBalance} to the
+     * corresponding framework API 2 representations.
+     */
     @Test
     public void camera2SettingsSetOptionsAndGetRequestSettings() throws CameraAccessException {
+        // We're only testing the focus modes, scene modes and white balances,
+        // and won't use the activeArray, previewSize, or photoSize. The
+        // constructor requires the former, so pass a degenerate rectangle.
         AndroidCamera2Settings set = new AndroidCamera2Settings(
-                mCamera, CameraDevice.TEMPLATE_PREVIEW, null, null, null);
+                mCamera, CameraDevice.TEMPLATE_PREVIEW, /*activeArray*/new Rect(),
+                /*previewSize*/null, /*photoSize*/null);
 
         // Focus modes
         set.setFocusMode(FocusMode.AUTO);
@@ -158,6 +183,11 @@
 
     // TODO: Add a test checking whether stringification matches API 1 representation
 
+    /**
+     * Ensure that {@code AndroidCamera2Capabilities#.*FromInt} correctly
+     * translates from framework API 2 representations to the equivalent
+     * {@code FocusMode}s, {@code SceneMode}s, and {@code WhiteBalance}s.
+     */
     @Test
     public void camera2CapabilitiesFocusModeFromInt() throws CameraAccessException {
         CameraCharacteristics chars = buildFrameworkCharacteristics();
diff --git a/camera2/public/src/com/android/ex/camera2/blocking/BlockingCameraManager.java b/camera2/public/src/com/android/ex/camera2/blocking/BlockingCameraManager.java
index 02dbbba..407a08a 100644
--- a/camera2/public/src/com/android/ex/camera2/blocking/BlockingCameraManager.java
+++ b/camera2/public/src/com/android/ex/camera2/blocking/BlockingCameraManager.java
@@ -66,7 +66,7 @@
 
         /**
          * Returns the error code {@link ERROR_DISCONNECTED} if disconnected, or one of
-         * {@code CameraDevice.StateListener#ERROR_*} if there was another error.
+         * {@code CameraDevice.StateCallback#ERROR_*} if there was another error.
          *
          * @return int Disconnect/error code
          */
@@ -81,7 +81,7 @@
          * @param errorCode
          * @param message
          *
-         * @see {@link CameraDevice.StateListener#ERROR_CAMERA_DEVICE}
+         * @see {@link CameraDevice.StateCallback#ERROR_CAMERA_DEVICE}
          */
         public BlockingOpenException(int errorCode, String message) {
             super(message);
@@ -117,8 +117,8 @@
      * does.</p>
      *
      * <p>Throws {@link BlockingOpenException} when the open fails asynchronously (due to
-     * {@link CameraDevice.StateListener#onDisconnected(CameraDevice)} or
-     * ({@link CameraDevice.StateListener#onError(CameraDevice)}.</p>
+     * {@link CameraDevice.StateCallback#onDisconnected(CameraDevice)} or
+     * ({@link CameraDevice.StateCallback#onError(CameraDevice)}.</p>
      *
      * <p>Throws {@link TimeoutRuntimeException} if opening times out. This is usually
      * highly unrecoverable, and all future calls to opening that camera will fail since the
@@ -142,7 +142,7 @@
      * @throws TimeoutRuntimeException
      *            If opening times out. Typically unrecoverable.
      */
-    public CameraDevice openCamera(String cameraId, CameraDevice.StateListener listener,
+    public CameraDevice openCamera(String cameraId, CameraDevice.StateCallback listener,
             Handler handler) throws CameraAccessException, BlockingOpenException {
 
         if (handler == null) {
@@ -163,17 +163,17 @@
     /**
      * Block until CameraManager#openCamera finishes with onOpened/onError/onDisconnected
      *
-     * <p>Pass-through all StateListener changes to the proxy.</p>
+     * <p>Pass-through all StateCallback changes to the proxy.</p>
      *
      * <p>Time out after {@link #OPEN_TIME_OUT} and unblock. Clean up camera if it arrives
      * later.</p>
      */
-    private class OpenListener extends CameraDevice.StateListener {
+    private class OpenListener extends CameraDevice.StateCallback {
         private static final int ERROR_UNINITIALIZED = -1;
 
         private final String mCameraId;
 
-        private final CameraDevice.StateListener mProxy;
+        private final CameraDevice.StateCallback mProxy;
 
         private final Object mLock = new Object();
         private final ConditionVariable mDeviceReady = new ConditionVariable();
@@ -187,7 +187,7 @@
         private boolean mTimedOut = false;
 
         OpenListener(CameraManager manager, String cameraId,
-                CameraDevice.StateListener listener, Handler handler)
+                CameraDevice.StateCallback listener, Handler handler)
                 throws CameraAccessException {
             mCameraId = cameraId;
             mProxy = listener;
diff --git a/camera2/public/src/com/android/ex/camera2/blocking/BlockingCaptureListener.java b/camera2/public/src/com/android/ex/camera2/blocking/BlockingCaptureCallback.java
similarity index 93%
rename from camera2/public/src/com/android/ex/camera2/blocking/BlockingCaptureListener.java
rename to camera2/public/src/com/android/ex/camera2/blocking/BlockingCaptureCallback.java
index eae85d1..4fb2c43 100644
--- a/camera2/public/src/com/android/ex/camera2/blocking/BlockingCaptureListener.java
+++ b/camera2/public/src/com/android/ex/camera2/blocking/BlockingCaptureCallback.java
@@ -36,7 +36,7 @@
  *
  * @see #getStateWaiter
  */
-public class BlockingCaptureListener extends CameraCaptureSession.CaptureListener {
+public class BlockingCaptureCallback extends CameraCaptureSession.CaptureCallback {
 
     /**
      * {@link #onCaptureStarted} has been called.
@@ -80,10 +80,10 @@
             "CAPTURE_SEQUENCE_ABORTED"
     };
 
-    private static final String TAG = "BlockingCaptureListener";
+    private static final String TAG = "BlockingCaptureCallback";
     private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
 
-    private final CameraCaptureSession.CaptureListener mProxy;
+    private final CameraCaptureSession.CaptureCallback mProxy;
 
     private final StateWaiter mStateWaiter = new StateWaiter(sStateNames);
     private final StateChangeListener mStateChangeListener = mStateWaiter.getListener();
@@ -92,7 +92,7 @@
      * Create a blocking capture listener without forwarding the capture listener invocations
      * to another capture listener.
      */
-    public BlockingCaptureListener() {
+    public BlockingCaptureCallback() {
         mProxy = null;
     }
 
@@ -104,7 +104,7 @@
      *
      * @throws NullPointerException if {@code listener} was {@code null}
      */
-    public BlockingCaptureListener(CameraCaptureSession.CaptureListener listener) {
+    public BlockingCaptureCallback(CameraCaptureSession.CaptureCallback listener) {
         if (listener == null) {
             throw new NullPointerException("listener must not be null");
         }
diff --git a/camera2/public/src/com/android/ex/camera2/blocking/BlockingSessionListener.java b/camera2/public/src/com/android/ex/camera2/blocking/BlockingSessionCallback.java
similarity index 93%
rename from camera2/public/src/com/android/ex/camera2/blocking/BlockingSessionListener.java
rename to camera2/public/src/com/android/ex/camera2/blocking/BlockingSessionCallback.java
index 26bb652..e041d27 100644
--- a/camera2/public/src/com/android/ex/camera2/blocking/BlockingSessionListener.java
+++ b/camera2/public/src/com/android/ex/camera2/blocking/BlockingSessionCallback.java
@@ -36,11 +36,11 @@
  * <p>Provides a waiter that can be used to block until the next unobserved state of the
  * requested type arrives.</p>
  *
- * <p>Pass-through all StateListener changes to the proxy.</p>
+ * <p>Pass-through all StateCallback changes to the proxy.</p>
  *
  * @see #getStateWaiter
  */
-public class BlockingSessionListener extends CameraCaptureSession.StateListener {
+public class BlockingSessionCallback extends CameraCaptureSession.StateCallback {
     /**
      * Session is configured, ready for captures
      */
@@ -71,10 +71,10 @@
     /*
      * Private fields
      */
-    private static final String TAG = "BlockingSessionListener";
+    private static final String TAG = "BlockingSessionCallback";
     private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
 
-    private final CameraCaptureSession.StateListener mProxy;
+    private final CameraCaptureSession.StateCallback mProxy;
     private final SessionFuture mSessionFuture = new SessionFuture();
 
     private final StateWaiter mStateWaiter = new StateWaiter(sStateNames);
@@ -92,7 +92,7 @@
      * Create a blocking session listener without forwarding the session listener invocations
      * to another session listener.
      */
-    public BlockingSessionListener() {
+    public BlockingSessionCallback() {
         mProxy = null;
     }
 
@@ -104,7 +104,7 @@
      *
      * @throws NullPointerException if {@code listener} was {@code null}
      */
-    public BlockingSessionListener(CameraCaptureSession.StateListener listener) {
+    public BlockingSessionCallback(CameraCaptureSession.StateCallback listener) {
         if (listener == null) {
             throw new NullPointerException("listener must not be null");
         }
@@ -142,7 +142,7 @@
     }
 
     /*
-     * CameraCaptureSession.StateListener implementation
+     * CameraCaptureSession.StateCallback implementation
      */
 
     @Override
diff --git a/camera2/public/src/com/android/ex/camera2/blocking/BlockingStateListener.java b/camera2/public/src/com/android/ex/camera2/blocking/BlockingStateCallback.java
similarity index 94%
rename from camera2/public/src/com/android/ex/camera2/blocking/BlockingStateListener.java
rename to camera2/public/src/com/android/ex/camera2/blocking/BlockingStateCallback.java
index 02c2ba3..5f93fbc 100644
--- a/camera2/public/src/com/android/ex/camera2/blocking/BlockingStateListener.java
+++ b/camera2/public/src/com/android/ex/camera2/blocking/BlockingStateCallback.java
@@ -36,14 +36,14 @@
  * the last wait, or that will be received from the camera device in the
  * future.</p>
  *
- * <p>Pass-through all StateListener changes to the proxy.</p>
+ * <p>Pass-through all StateCallback changes to the proxy.</p>
  *
  */
-public class BlockingStateListener extends CameraDevice.StateListener {
-    private static final String TAG = "BlockingStateListener";
+public class BlockingStateCallback extends CameraDevice.StateCallback {
+    private static final String TAG = "BlockingStateCallback";
     private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
 
-    private final CameraDevice.StateListener mProxy;
+    private final CameraDevice.StateCallback mProxy;
 
     // Guards mWaiting
     private final Object mLock = new Object();
@@ -99,11 +99,11 @@
      */
     private static int NUM_STATES = 4;
 
-    public BlockingStateListener() {
+    public BlockingStateCallback() {
         mProxy = null;
     }
 
-    public BlockingStateListener(CameraDevice.StateListener listener) {
+    public BlockingStateCallback(CameraDevice.StateCallback listener) {
         mProxy = listener;
     }
 
diff --git a/camera2/public/src/com/android/ex/camera2/pos/AutoFocusStateMachine.java b/camera2/public/src/com/android/ex/camera2/pos/AutoFocusStateMachine.java
index 9fa2af2..e8a3ab6 100644
--- a/camera2/public/src/com/android/ex/camera2/pos/AutoFocusStateMachine.java
+++ b/camera2/public/src/com/android/ex/camera2/pos/AutoFocusStateMachine.java
@@ -91,7 +91,7 @@
 
     /**
      * Invoke every time we get a new CaptureResult via
-     * {@link CameraDevice.CaptureListener#onCaptureCompleted}.
+     * {@link CameraDevice.CaptureCallback#onCaptureCompleted}.
      *
      * <p>This function is responsible for dispatching updates via the
      * {@link AutoFocusStateListener} so without calling this on a regular basis, no
diff --git a/camera2/utils/src/com/android/ex/camera2/utils/Camera2CaptureListenerForwarder.java b/camera2/utils/src/com/android/ex/camera2/utils/Camera2CaptureCallbackForwarder.java
similarity index 90%
rename from camera2/utils/src/com/android/ex/camera2/utils/Camera2CaptureListenerForwarder.java
rename to camera2/utils/src/com/android/ex/camera2/utils/Camera2CaptureCallbackForwarder.java
index 35b1c6d..97b5b6e 100644
--- a/camera2/utils/src/com/android/ex/camera2/utils/Camera2CaptureListenerForwarder.java
+++ b/camera2/utils/src/com/android/ex/camera2/utils/Camera2CaptureCallbackForwarder.java
@@ -17,7 +17,7 @@
 package com.android.ex.camera2.utils;
 
 import android.hardware.camera2.CameraCaptureSession;
-import android.hardware.camera2.CameraCaptureSession.CaptureListener;
+import android.hardware.camera2.CameraCaptureSession.CaptureCallback;
 import android.hardware.camera2.CaptureFailure;
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.CaptureResult;
@@ -25,14 +25,14 @@
 import android.os.Handler;
 
 /**
- * Proxy that forwards all updates to another {@link CaptureListener}, invoking
+ * Proxy that forwards all updates to another {@link CaptureCallback}, invoking
  * its callbacks on a separate {@link Handler}.
  */
-public class Camera2CaptureListenerForwarder extends CaptureListener {
-    private CaptureListener mListener;
+public class Camera2CaptureCallbackForwarder extends CaptureCallback {
+    private CaptureCallback mListener;
     private Handler mHandler;
 
-    public Camera2CaptureListenerForwarder(CaptureListener listener, Handler handler) {
+    public Camera2CaptureCallbackForwarder(CaptureCallback listener, Handler handler) {
         mListener = listener;
         mHandler = handler;
     }
diff --git a/camera2/utils/src/com/android/ex/camera2/utils/Camera2CaptureListenerSplitter.java b/camera2/utils/src/com/android/ex/camera2/utils/Camera2CaptureCallbackSplitter.java
similarity index 79%
rename from camera2/utils/src/com/android/ex/camera2/utils/Camera2CaptureListenerSplitter.java
rename to camera2/utils/src/com/android/ex/camera2/utils/Camera2CaptureCallbackSplitter.java
index a13dc04..f813076 100644
--- a/camera2/utils/src/com/android/ex/camera2/utils/Camera2CaptureListenerSplitter.java
+++ b/camera2/utils/src/com/android/ex/camera2/utils/Camera2CaptureCallbackSplitter.java
@@ -17,7 +17,7 @@
 package com.android.ex.camera2.utils;
 
 import android.hardware.camera2.CameraCaptureSession;
-import android.hardware.camera2.CameraCaptureSession.CaptureListener;
+import android.hardware.camera2.CameraCaptureSession.CaptureCallback;
 import android.hardware.camera2.CaptureFailure;
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.CaptureResult;
@@ -28,18 +28,18 @@
 import java.util.List;
 
 /**
- * Junction that allows notifying multiple {@link CaptureListener}s whenever
+ * Junction that allows notifying multiple {@link CaptureCallback}s whenever
  * the {@link CameraCaptureSession} posts a capture-related update.
  */
-public class Camera2CaptureListenerSplitter extends CaptureListener {
-    private final List<CaptureListener> mRecipients = new LinkedList<>();
+public class Camera2CaptureCallbackSplitter extends CaptureCallback {
+    private final List<CaptureCallback> mRecipients = new LinkedList<>();
 
     /**
      * @param recipients The listeners to notify. Any {@code null} passed here
      *                   will be completely ignored.
      */
-    public Camera2CaptureListenerSplitter(CaptureListener... recipients) {
-        for (CaptureListener listener : recipients) {
+    public Camera2CaptureCallbackSplitter(CaptureCallback... recipients) {
+        for (CaptureCallback listener : recipients) {
             if (listener != null) {
                 mRecipients.add(listener);
             }
@@ -49,7 +49,7 @@
     @Override
     public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
                                    TotalCaptureResult result) {
-        for (CaptureListener target : mRecipients) {
+        for (CaptureCallback target : mRecipients) {
             target.onCaptureCompleted(session, request, result);
         }
     }
@@ -57,7 +57,7 @@
     @Override
     public void onCaptureFailed(CameraCaptureSession session, CaptureRequest request,
                                 CaptureFailure failure) {
-        for (CaptureListener target : mRecipients) {
+        for (CaptureCallback target : mRecipients) {
             target.onCaptureFailed(session, request, failure);
         }
     }
@@ -65,14 +65,14 @@
     @Override
     public void onCaptureProgressed(CameraCaptureSession session, CaptureRequest request,
                                     CaptureResult partialResult) {
-        for (CaptureListener target : mRecipients) {
+        for (CaptureCallback target : mRecipients) {
             target.onCaptureProgressed(session, request, partialResult);
         }
     }
 
     @Override
     public void onCaptureSequenceAborted(CameraCaptureSession session, int sequenceId) {
-        for (CaptureListener target : mRecipients) {
+        for (CaptureCallback target : mRecipients) {
             target.onCaptureSequenceAborted(session, sequenceId);
         }
     }
@@ -80,7 +80,7 @@
     @Override
     public void onCaptureSequenceCompleted(CameraCaptureSession session, int sequenceId,
                                            long frameNumber) {
-        for (CaptureListener target : mRecipients) {
+        for (CaptureCallback target : mRecipients) {
             target.onCaptureSequenceCompleted(session, sequenceId, frameNumber);
         }
     }
@@ -88,7 +88,7 @@
     @Override
     public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request,
                                  long timestamp) {
-        for (CaptureListener target : mRecipients) {
+        for (CaptureCallback target : mRecipients) {
             target.onCaptureStarted(session, request, timestamp);
         }
     }
diff --git a/camera2/utils/src/com/android/ex/camera2/utils/Camera2RequestSettingsSet.java b/camera2/utils/src/com/android/ex/camera2/utils/Camera2RequestSettingsSet.java
index fac8f1a..6e1d825 100644
--- a/camera2/utils/src/com/android/ex/camera2/utils/Camera2RequestSettingsSet.java
+++ b/camera2/utils/src/com/android/ex/camera2/utils/Camera2RequestSettingsSet.java
@@ -146,7 +146,7 @@
      * to its default value or simply unset. While {@link #get} will return
      * {@code null} in both these cases, this method will return {@code true}
      * and {@code false}, respectively.</p>
-
+     *
      * @param key Which setting to look for.
      * @return Whether that setting has a value that will propagate with unions.
      *
@@ -160,8 +160,23 @@
     }
 
     /**
+     * Check whether the value of the specified setting matches the given one.
+     *
+     * <p>This method uses the {@code T} type's {@code equals} method, but is
+     * {@code null}-tolerant.</p>
+     *
+     * @param key Which of this class's settings to check.
+     * @param value Value to test for equality against.
+     * @return Whether they are the same.
+     */
+    public <T> boolean matches(Key<T> key, T value) {
+        return Objects.equals(get(key), value);
+    }
+
+    /**
      * Get this set of settings's revision identifier, which can be compared
      * against cached past values to determine whether it has been modified.
+     *
      * <p>Distinct revisions across the same object do not necessarily indicate
      * that the object's key/value pairs have changed at all, but the same
      * revision on the same object does imply that they've stayed the same.</p>
diff --git a/camera2/utils/tests/src/com/android/ex/camera2/utils/Camera2DeviceTester.java b/camera2/utils/tests/src/com/android/ex/camera2/utils/Camera2DeviceTester.java
index 4db6dfb..e8639ba 100644
--- a/camera2/utils/tests/src/com/android/ex/camera2/utils/Camera2DeviceTester.java
+++ b/camera2/utils/tests/src/com/android/ex/camera2/utils/Camera2DeviceTester.java
@@ -52,7 +52,7 @@
     @InjectContext
     public Context mContext;
 
-    private class DeviceCapturer extends CameraDevice.StateListener {
+    private class DeviceCapturer extends CameraDevice.StateCallback {
         private CameraDevice mCamera;
 
         public CameraDevice captureCameraDevice() throws Exception {
diff --git a/camera2/utils/tests/src/com/android/ex/camera2/utils/Camera2UtilsTest.java b/camera2/utils/tests/src/com/android/ex/camera2/utils/Camera2UtilsTest.java
index bb23e37..3156cf7 100644
--- a/camera2/utils/tests/src/com/android/ex/camera2/utils/Camera2UtilsTest.java
+++ b/camera2/utils/tests/src/com/android/ex/camera2/utils/Camera2UtilsTest.java
@@ -23,7 +23,8 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 
-import android.hardware.camera2.CameraCaptureSession.CaptureListener;
+import android.graphics.Rect;
+import android.hardware.camera2.CameraCaptureSession.CaptureCallback;
 import android.hardware.camera2.CameraDevice;
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.CaptureRequest.Key;
@@ -32,65 +33,65 @@
 import org.junit.Test;
 
 public class Camera2UtilsTest extends Camera2DeviceTester {
-    private void captureListenerSplitterAllCallbacksReceived(CaptureListener splitter,
-                                                             CaptureListener... terminals) {
+    private void captureListenerSplitterAllCallbacksReceived(CaptureCallback splitter,
+                                                             CaptureCallback... terminals) {
         splitter.onCaptureCompleted(null, null, null);
-        for (CaptureListener each : terminals) {
+        for (CaptureCallback each : terminals) {
             verify(each).onCaptureCompleted(null, null, null);
         }
         splitter.onCaptureFailed(null, null, null);
-        for (CaptureListener each : terminals) {
+        for (CaptureCallback each : terminals) {
             verify(each).onCaptureFailed(null, null, null);
         }
         splitter.onCaptureProgressed(null, null, null);
-        for (CaptureListener each : terminals) {
+        for (CaptureCallback each : terminals) {
             verify(each).onCaptureProgressed(null, null, null);
         }
         splitter.onCaptureSequenceAborted(null, 0);
-        for (CaptureListener each : terminals) {
+        for (CaptureCallback each : terminals) {
             verify(each).onCaptureSequenceAborted(null, 0);
         }
         splitter.onCaptureSequenceCompleted(null, 0, 0L);
-        for (CaptureListener each : terminals) {
+        for (CaptureCallback each : terminals) {
             verify(each).onCaptureSequenceCompleted(null, 0, 0L);
         }
         splitter.onCaptureStarted(null, null, 0L);
-        for (CaptureListener each : terminals) {
+        for (CaptureCallback each : terminals) {
             verify(each).onCaptureStarted(null, null, 0L);
         }
     }
 
     @Test
     public void captureListenerSplitter() {
-        CaptureListener firstBackingListener = mock(CaptureListener.class);
-        CaptureListener secondBackingListener = mock(CaptureListener.class);
+        CaptureCallback firstBackingListener = mock(CaptureCallback.class);
+        CaptureCallback secondBackingListener = mock(CaptureCallback.class);
         captureListenerSplitterAllCallbacksReceived(
-                new Camera2CaptureListenerSplitter(firstBackingListener, secondBackingListener),
+                new Camera2CaptureCallbackSplitter(firstBackingListener, secondBackingListener),
                 firstBackingListener, secondBackingListener);
     }
 
     @Test
     public void captureListenerSplitterEmpty() {
-        captureListenerSplitterAllCallbacksReceived(new Camera2CaptureListenerSplitter());
+        captureListenerSplitterAllCallbacksReceived(new Camera2CaptureCallbackSplitter());
     }
 
     @Test
     public void captureListenerSplitterNoNpe() {
         captureListenerSplitterAllCallbacksReceived(
-                new Camera2CaptureListenerSplitter((CaptureListener) null));
+                new Camera2CaptureCallbackSplitter((CaptureCallback) null));
     }
 
     @Test
     public void captureListenerSplitterMultipleNulls() {
         captureListenerSplitterAllCallbacksReceived(
-                new Camera2CaptureListenerSplitter(null, null, null));
+                new Camera2CaptureCallbackSplitter(null, null, null));
     }
 
     @Test
     public void captureListenerSplitterValidAndNull() {
-        CaptureListener onlyRealBackingListener = mock(CaptureListener.class);
+        CaptureCallback onlyRealBackingListener = mock(CaptureCallback.class);
         captureListenerSplitterAllCallbacksReceived(
-                new Camera2CaptureListenerSplitter(null, onlyRealBackingListener),
+                new Camera2CaptureCallbackSplitter(null, onlyRealBackingListener),
                 onlyRealBackingListener);
     }
 
@@ -234,22 +235,61 @@
         setUp.get(null);
     }
 
+    @Test
+    public void requestSettingsSetMatchesPrimitives() {
+        Camera2RequestSettingsSet setUp = new Camera2RequestSettingsSet();
+        assertTrue(setUp.matches(CaptureRequest.CONTROL_AE_LOCK, null));
+        assertFalse(setUp.matches(CaptureRequest.CONTROL_AE_LOCK, false));
+        assertFalse(setUp.matches(CaptureRequest.CONTROL_AE_LOCK, true));
+
+        setUp.set(CaptureRequest.CONTROL_AE_LOCK, null);
+        assertTrue(setUp.matches(CaptureRequest.CONTROL_AE_LOCK, null));
+        assertFalse(setUp.matches(CaptureRequest.CONTROL_AE_LOCK, false));
+        assertFalse(setUp.matches(CaptureRequest.CONTROL_AE_LOCK, true));
+
+        setUp.set(CaptureRequest.CONTROL_AE_LOCK, false);
+        assertFalse(setUp.matches(CaptureRequest.CONTROL_AE_LOCK, null));
+        assertTrue(setUp.matches(CaptureRequest.CONTROL_AE_LOCK, false));
+        assertFalse(setUp.matches(CaptureRequest.CONTROL_AE_LOCK, true));
+
+        setUp.set(CaptureRequest.CONTROL_AE_LOCK, true);
+        assertFalse(setUp.matches(CaptureRequest.CONTROL_AE_LOCK, null));
+        assertFalse(setUp.matches(CaptureRequest.CONTROL_AE_LOCK, false));
+        assertTrue(setUp.matches(CaptureRequest.CONTROL_AE_LOCK, true));
+    }
+
+    @Test
+    public void requestSettingsSetMatchesReferences() {
+        Camera2RequestSettingsSet setUp = new Camera2RequestSettingsSet();
+        assertTrue(setUp.matches(CaptureRequest.SCALER_CROP_REGION, null));
+        assertFalse(setUp.matches(CaptureRequest.SCALER_CROP_REGION, new Rect(0, 0, 0, 0)));
+
+        setUp.set(CaptureRequest.SCALER_CROP_REGION, null);
+        assertTrue(setUp.matches(CaptureRequest.SCALER_CROP_REGION, null));
+        assertFalse(setUp.matches(CaptureRequest.SCALER_CROP_REGION, new Rect(0, 0, 0, 0)));
+
+        setUp.set(CaptureRequest.SCALER_CROP_REGION, new Rect(0, 0, 0, 0));
+        assertFalse(setUp.matches(CaptureRequest.SCALER_CROP_REGION, null));
+        assertTrue(setUp.matches(CaptureRequest.SCALER_CROP_REGION, new Rect(0, 0, 0, 0)));
+        assertFalse(setUp.matches(CaptureRequest.SCALER_CROP_REGION, new Rect(0, 0, 1, 1)));
+    }
+
     @Test(expected=NullPointerException.class)
     public void requestSettingsSetNullArgToCreateRequest0() throws Exception {
         Camera2RequestSettingsSet setUp = new Camera2RequestSettingsSet();
-        setUp.createRequest(null, 0);
+        setUp.createRequest(null, CameraDevice.TEMPLATE_PREVIEW);
     }
 
     @Test(expected=NullPointerException.class)
     public void requestSettingsSetNullArgToCreateRequest2() throws Exception {
         Camera2RequestSettingsSet setUp = new Camera2RequestSettingsSet();
-        setUp.createRequest(mCamera, 0, (Surface) null);
+        setUp.createRequest(mCamera, CameraDevice.TEMPLATE_PREVIEW, (Surface) null);
     }
 
     @Test(expected=NullPointerException.class)
     public void requestSettingsSetNullArgToCreateRequest02() throws Exception {
         Camera2RequestSettingsSet setUp = new Camera2RequestSettingsSet();
-        setUp.createRequest(null, 0, (Surface) null);
+        setUp.createRequest(null, CameraDevice.TEMPLATE_PREVIEW, (Surface) null);
     }
 
     @Test
diff --git a/carousel/Android.mk b/carousel/Android.mk
deleted file mode 100644
index 1f2592f..0000000
--- a/carousel/Android.mk
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright (C) 2009 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.
-
-LOCAL_PATH := $(call my-dir)
-
-# Note: the source code is in java/, not src/, because this code is also part of
-# the framework library, and build/core/pathmap.mk expects a java/ subdirectory.
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := android-common-carousel
-LOCAL_SRC_FILES := \
-     $(call all-java-files-under, java) \
-     $(call all-logtags-files-under, java) \
-     $(call all-renderscript-files-under, java)
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/carousel/java/com/android/ex/carousel/CarouselController.java b/carousel/java/com/android/ex/carousel/CarouselController.java
deleted file mode 100644
index 8bb9c01..0000000
--- a/carousel/java/com/android/ex/carousel/CarouselController.java
+++ /dev/null
@@ -1,842 +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 com.android.ex.carousel.CarouselRS.CarouselCallback;
-import com.android.ex.carousel.CarouselView.DetailAlignment;
-
-import android.graphics.Bitmap;
-import android.renderscript.Float4;
-import android.renderscript.Mesh;
-import android.renderscript.RenderScriptGL;
-import android.util.Log;
-
-/**
- * <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 class CarouselController {
-    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 int DEFAULT_ROW_COUNT = 1;
-    private final float DEFAULT_OVERSCROLL_SLOTS = 1.0f;
-    private final float DEFAULT_ROW_SPACING = 0.0f;
-    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 CarouselRS mRenderScript;
-    private RenderScriptGL mRS;
-    private static final String TAG = "CarouselController";
-    private static final boolean DBG = false;
-
-    // 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 int mDefaultGeometry;
-    private int mLoadingGeometry;
-    private float[] mDefaultCardMatrix;
-    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 mForceBlendCardsWithZ = false;
-    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 mOverscrollSlots = DEFAULT_OVERSCROLL_SLOTS;
-    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 int mRowCount = DEFAULT_ROW_COUNT;
-    private float mRowSpacing = DEFAULT_ROW_SPACING;
-    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 long mCardCreationFadeDuration = 0L;
-    private Bitmap mDetailLoadingBitmap = Bitmap.createBitmap(
-            new int[] {0}, 0, 1, 1, 1, Bitmap.Config.ARGB_4444);
-    private int mDragModel = CarouselRS.DRAG_MODEL_SCREEN_DELTA;
-    private int mFillDirection = CarouselRS.FILL_DIRECTION_CCW;
-    private boolean mFirstCardTop = false;
-    private int[] mStoreConfigs;
-
-    public CarouselController() {
-        boolean useDepthBuffer = true;
-    }
-
-    public void setRS(RenderScriptGL rs, CarouselRS renderScript) {
-        mRS = rs;
-        mRenderScript = renderScript;
-    }
-
-    public void onSurfaceChanged() {
-        setSlotCount(mSlotCount);
-        setDefaultCardMatrix(mDefaultCardMatrix);
-        createCards(mCardCount);
-        setVisibleSlots(mVisibleSlots);
-        setVisibleDetails(mVisibleDetails);
-        setPrefetchCardCount(mPrefetchCardCount);
-        setOverscrollSlots(mOverscrollSlots);
-        setRowCount(mRowCount);
-        setRowSpacing(mRowSpacing);
-        setFirstCardTop(mFirstCardTop);
-        setDetailTextureAlignment(mDetailTextureAlignment);
-        setForceBlendCardsWithZ(mForceBlendCardsWithZ);
-        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);
-        setDragModel(mDragModel);
-        setFillDirection(mFillDirection);
-        setLookAt(mEye, mAt, mUp);
-        setRezInCardCount(mRezInCardCount);
-        setFadeInDuration(mFadeInDuration);
-        setCardCreationFadeDuration(mCardCreationFadeDuration);
-        setDetailLoadingBitmap(mDetailLoadingBitmap);
-        setStoreConfigs(mStoreConfigs);
-    }
-
-    /**
-     * Loads geometry from a resource id.
-     *
-     * @param resId
-     * @return the loaded mesh or null if it cannot be loaded
-     */
-    public Mesh loadGeometry(int resId) {
-        if (mRenderScript != null) {
-          return mRenderScript.loadGeometry(resId);
-        }
-        return null;
-    }
-
-    /**
-     * Set the geometry to show for a given slot.
-     * @param n The card to set the geometry for
-     * @param mesh The geometry for that item
-     * @see {@link #setDefaultGeometry}
-     */
-    public void setGeometryForItem(int n, Mesh mesh) {
-        if (mRenderScript != null) {
-            mRenderScript.setGeometry(n, mesh);
-        }
-    }
-
-    /**
-     * Load A3D file from resource. If resId == 0, will clear geometry for this item.
-     * @param n The card to set the geometry for
-     * @param resId The resource ID for the geometry for that item
-     * @see {@link #setDefaultGeometry}
-     */
-    public void setGeometryForItem(int n, int resId) {
-        if (mRenderScript != null) {
-            Mesh mesh = mRenderScript.loadGeometry(resId);
-            mRenderScript.setGeometry(n, mesh);
-        }
-    }
-
-    /**
-     * Set the matrix for the specified card
-     * @param n The card to set the matrix for
-     * @param matrix The matrix to use
-     * @see {@link #setDefaultGeometry}
-     */
-    public void setMatrixForItem(int n, float[] matrix) {
-        if (mRenderScript != null) {
-            mRenderScript.setMatrix(n, matrix);
-        }
-    }
-
-    /**
-     * 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) {
-        mSlotCount = n;
-        if (mRenderScript != null) {
-            mRenderScript.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) {
-        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);
-        }
-    }
-
-    /**
-     * 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) {
-        mPrefetchCardCount = n;
-        if (mRenderScript != null) {
-            mRenderScript.setPrefetchCardCount(n);
-        }
-    }
-
-    /**
-     * Sets the number of rows of cards to show in each slot.
-     */
-    public void setRowCount(int n) {
-        mRowCount = n;
-        if (mRenderScript != null) {
-            mRenderScript.setRowCount(n);
-        }
-    }
-
-    /**
-     * Sets the spacing between each row of cards when rowCount > 1.
-     */
-    public void setRowSpacing(float s) {
-        mRowSpacing = s;
-        if (mRenderScript != null) {
-            mRenderScript.setRowSpacing(s);
-        }
-    }
-
-     /**
-     * Sets the position of the first card when rowCount > 1 .
-     */
-    public void setFirstCardTop(boolean f) {
-        mFirstCardTop = f;
-        if (mRenderScript != null) {
-            mRenderScript.setFirstCardTop(f);
-        }
-    }
-
-    /**
-     * Sets the amount of allowed overscroll (in slots)
-     */
-    public void setOverscrollSlots(float slots) {
-        mOverscrollSlots = slots;
-        if (mRenderScript != null) {
-            mRenderScript.setOverscrollSlots(slots);
-        }
-    }
-
-    /**
-     * 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);
-        }
-    }
-
-    /**
-     * Set whether depth is enabled while blending. Generally, this is discouraged because
-     * it causes bad artifacts. Careful attention to geometry and alpha transparency of
-     * textures can mitigate much of this. Geometry for an individual item must be drawn
-     * back-to-front, for example.
-     *
-     * @param enabled True to enable depth while blending, and false to disable it.
-     */
-    public void setForceBlendCardsWithZ(boolean enabled) {
-        mForceBlendCardsWithZ = enabled;
-        if (mRenderScript != null) {
-            mRenderScript.setForceBlendCardsWithZ(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) {
-        mDrawRuler = drawRuler;
-        if (mRenderScript != null) {
-            mRenderScript.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) {
-        mCardCount = n;
-        if (mRenderScript != null) {
-            mRenderScript.createCards(n);
-        }
-    }
-
-    public int getCardCount() {
-        return mCardCount;
-    }
-
-    /**
-     * 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) {
-        // 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");
-        }
-    }
-
-    /**
-     * 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) {
-        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");
-        }
-    }
-
-    /**
-     * Sets the specified texture as invalid. If {@code eraseCurrent} is true,
-     * the texture will be immediately cleared from view and an invalidate
-     * handler will be called. If {@code eraseCurrent} is false, a replacement
-     * texture will be requested, and the old texture will be left in place in
-     * the meantime.
-     *
-     * @param n the card to invalidate the detail texture for
-     * @param eraseCurrent whether to erase the current texture
-     */
-    public void invalidateTexture(int n, boolean eraseCurrent) {
-        if (mRenderScript != null && mRS != null) {
-            if (DBG) Log.v(TAG, "invalidateTexture(" + n + ", " + eraseCurrent + ")");
-            mRenderScript.invalidateTexture(n, eraseCurrent);
-            if (DBG) Log.v(TAG, "done");
-        }
-    }
-
-    /**
-     * Sets the specified detail texture as invalid. If eraseCurrent is true, the texture will be
-     * immediately cleared from view and an invalidate handler will be called. If eraseCurrent is
-     * false, a replacement texture will be requested, and the old texture will be left in place
-     * in the meantime.
-     * @param n the card to invalidate the detail texture for
-     * @param eraseCurrent whether to erase the current texture
-     */
-    public void invalidateDetailTexture(int n, boolean eraseCurrent) {
-        if (mRenderScript != null && mRS != null) {
-            if (DBG) Log.v(TAG, "invalidateDetailTexture(" + n + ", " + eraseCurrent + ")");
-            mRenderScript.invalidateDetailTexture(n, eraseCurrent);
-            if (DBG) Log.v(TAG, "done");
-        }
-    }
-
-    /**
-     * 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) {
-        mDefaultBitmap = bitmap;
-        if (mRenderScript != null) {
-            mRenderScript.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) {
-        mLoadingBitmap = bitmap;
-        if (mRenderScript != null) {
-            mRenderScript.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) {
-        mBackgroundColor = new Float4(red, green, blue, alpha);
-        if (mRenderScript != null) {
-            mRenderScript.setBackgroundColor(mBackgroundColor);
-        }
-    }
-
-    /**
-     * Can be used to optionally set the background to a bitmap. When set to something other than
-     * null, this overrides {@link CarouselController#setBackgroundColor(Float4)}.
-     *
-     * @param bitmap
-     */
-    public void setBackgroundBitmap(Bitmap bitmap) {
-        mBackgroundBitmap = bitmap;
-        if (mRenderScript != null) {
-            mRenderScript.setBackgroundTexture(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) {
-        mDetailLoadingBitmap = bitmap;
-        if (mRenderScript != null) {
-            mRenderScript.setDetailLoadingTexture(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) {
-        mDefaultLineBitmap = bitmap;
-        if (mRenderScript != null) {
-            mRenderScript.setDetailLineTexture(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. If something other than
-     * simple planar geometry is used, consider enabling depth test with
-     * {@link CarouselController#setForceBlendCardsWithZ(boolean)}
-     *
-     * @param mesh
-     */
-    public void setDefaultGeometry(int resId) {
-        mDefaultGeometry = resId;
-        if (mRenderScript != null) {
-            Mesh mesh = mRenderScript.loadGeometry(resId);
-            mRenderScript.setDefaultGeometry(mesh);
-        }
-    }
-
-    /**
-     * Sets the matrix used to transform card geometries.  By default, this
-     * is the identity matrix, but you can specify a different matrix if you
-     * want to scale, translate and / or rotate the card before drawing.
-     *
-     * @param matrix array of 9 or 16 floats representing a 3x3 or 4x4 matrix,
-     * or null as a shortcut for an identity matrix.
-     */
-    public void setDefaultCardMatrix(float[] matrix) {
-        mDefaultCardMatrix = matrix;
-        if (mRenderScript != null) {
-           mRenderScript.setDefaultCardMatrix(matrix);
-        }
-    }
-
-    /**
-     * 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. If something other than
-     * simple planar geometry is used, consider enabling depth test with
-     * {@link CarouselView#setForceBlendCardsWithZ(boolean)}
-     *
-     * @param resId
-     */
-    public void setLoadingGeometry(int resId) {
-        mLoadingGeometry = resId;
-        if (mRenderScript != null) {
-            Mesh mesh = mRenderScript.loadGeometry(resId);
-            mRenderScript.setLoadingGeometry(mesh);
-        }
-    }
-
-    /**
-     * Sets the callback for receiving events from RenderScript.
-     *
-     * @param callback
-     */
-    public void setCallback(CarouselCallback callback)
-    {
-        mCarouselCallback = callback;
-        if (mRenderScript != null) {
-            mRenderScript.setCallback(callback);
-        }
-    }
-
-    /**
-     * Gets the callback for receiving events from Renderscript.
-     */
-    public CarouselCallback getCallback() {
-        return mCarouselCallback;
-    }
-
-    /**
-     * 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)
-    {
-        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);
-        }
-    }
-
-    /**
-     * Triggers a rotation of the carousel. All angles are in card units, see:
-     * {@link CarouselController#setCarouselRotationAngle(float)}) for more details.
-     *
-     * @param endAngle the card unit to which the carousel should rotate to
-     * @param milliseconds the length of the animation
-     * @param interpolationMode three modes are currently supported :
-     * {@link CarouselView.InterpolationMode#LINEAR}
-     * {@link CarouselView.InterpolationMode#DECELERATE_QUADRATIC}
-     * {@link CarouselView.InterpolationMode#ACCELERATE_DECELERATE_CUBIC}
-     * @param maxAnimatedArc the maximum angular distance over which the transition will be
-     * animated.
-     * If the current position is further away, it is set at maxAnimatedArc from endAngle.
-     * This parameter is ignored when <= 0.
-     */
-    public void setCarouselRotationAngle(float endAngle, int milliseconds, int interpolationMode,
-            float maxAnimatedArc) {
-        if (mRenderScript != null) {
-            mRenderScript.setCarouselRotationAngle(endAngle, milliseconds,
-                    interpolationMode, maxAnimatedArc);
-        }
-    }
-
-    public void setRadius(float radius) {
-        mRadius = radius;
-        if (mRenderScript != null) {
-            mRenderScript.setRadius(radius);
-        }
-    }
-
-    /**
-     * Sets the current model for dragging. There are currently four drag models:
-     * {@link CarouselView#DRAG_MODEL_SCREEN_DELTA}
-     * {@link CarouselView#DRAG_MODEL_PLANE}
-     * {@link CarouselView#DRAG_MODEL_CYLINDER_INSIDE}
-     * {@link CarouselView#DRAG_MODEL_CYLINDER_OUTSIDE}
-     *
-     * @param model
-     */
-    public void setDragModel(int model) {
-        mDragModel  = model;
-        if (mRenderScript != null) {
-            mRenderScript.setDragModel(model);
-        }
-    }
-
-    /** Sets the direction to fill in cards around the carousel.
-     *
-     * @param direction Either {@link CarouselRS#FILL_DIRECTION_CCW} or
-     * {@link CarouselRS#FILL_DIRECTION_CW}.
-     */
-    public void setFillDirection(int direction) {
-        mFillDirection = direction;
-        if (mRenderScript != null) {
-            mRenderScript.setFillDirection(direction);
-        }
-    }
-
-    public void setCardRotation(float cardRotation) {
-        mCardRotation = cardRotation;
-        if (mRenderScript != null) {
-            mRenderScript.setCardRotation(cardRotation);
-        }
-    }
-
-    public void setCardsFaceTangent(boolean faceTangent) {
-        mCardsFaceTangent = faceTangent;
-        if (mRenderScript != null) {
-            mRenderScript.setCardsFaceTangent(faceTangent);
-        }
-    }
-
-    public void setSwaySensitivity(float swaySensitivity) {
-        mSwaySensitivity = swaySensitivity;
-        if (mRenderScript != null) {
-            mRenderScript.setSwaySensitivity(swaySensitivity);
-        }
-    }
-
-    public void setFrictionCoefficient(float frictionCoefficient) {
-        mFrictionCoefficient = frictionCoefficient;
-        if (mRenderScript != null) {
-            mRenderScript.setFrictionCoefficient(frictionCoefficient);
-        }
-    }
-
-    public void setDragFactor(float dragFactor) {
-        mDragFactor = dragFactor;
-        if (mRenderScript != null) {
-            mRenderScript.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);
-        }
-    }
-
-    /**
-     * 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) {
-        mRezInCardCount = n;
-        if (mRenderScript != null) {
-            mRenderScript.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 The time, in milliseconds
-     */
-    public void setFadeInDuration(long t) {
-        mFadeInDuration = t;
-        if (mRenderScript != null) {
-            mRenderScript.setFadeInDuration(t);
-        }
-    }
-
-    /**
-     * This sets the duration (in ms) that a card takes to fade in when it is initially created,
-     * such as when it is added or when the application starts. The timer starts at the moment
-     * when the card is first created. Replacing a card's contents does not affect the timer.
-     * @param t The time, in milliseconds
-     */
-    public void setCardCreationFadeDuration(long t) {
-        mCardCreationFadeDuration = t;
-        if (mRenderScript != null) {
-            mRenderScript.setCardCreationFadeDuration(t);
-        }
-    }
-
-    /**
-     * Tells the carousel that a touch event has started at the designated location.
-     * @param x The number of pixels from the left edge that the event occurred
-     * @param y The number of pixels from the top edge that the event occurred
-     * @param t The time stamp of the event
-     */
-    public void onTouchStarted(float x, float y, long t) {
-        mRenderScript.doStart(x, y, t);
-    }
-
-    /**
-     * Tells the carousel that a touch event has moved to the designated location.
-     * @param x The number of pixels from the left edge that the event occurred
-     * @param y The number of pixels from the top edge that the event occurred
-     * @param t The time stamp of the event
-     */
-    public void onTouchMoved(float x, float y, long t) {
-        mRenderScript.doMotion(x, y, t);
-    }
-
-    /**
-     * Tells the carousel that the user has long-pressed.
-     */
-    public void onLongPress() {
-        mRenderScript.doLongPress();
-    }
-
-    /**
-     * Tells the carousel that a touch event has stopped at the designated location.
-     * @param x The number of pixels from the left edge that the event occurred
-     * @param y The number of pixels from the top edge that the event occurred
-     * @param t The time stamp of the event
-     */
-    public void onTouchStopped(float x, float y, long t) {
-        mRenderScript.doStop(x, y, t);
-    }
-
-    /**
-     * Whether to use alpha when drawing a primitive: on for translucent, off for opaque.
-     */
-    public static final int STORE_CONFIG_ALPHA = 1;
-
-    /**
-     * Whether to read from the depth buffer when rendering. Determines with glDepthFunc()
-     * is given GL_LESS or GL_ALWAYS. On for GL_LESS, off for GL_ALWAYS.
-     */
-    public static final int STORE_CONFIG_DEPTH_READS = 2;
-
-    /**
-     * Whether to write to the depth buffer when rendering. Passed to glDepthMask().
-     */
-    public static final int STORE_CONFIG_DEPTH_WRITES = 4;
-
-    /**
-     * Set the StoreConfig parameters that will be used for each mesh primitive.
-     *
-     * Each integer in the array is a bitfield composed of
-     * {@link CarouselController#STORE_CONFIG_ALPHA},
-     * {@link CarouselController#STORE_CONFIG_DEPTH_READS}, and
-     * {@link CarouselController#STORE_CONFIG_DEPTH_WRITES}.
-     *
-     * These parameters MUST correspond to primitives in geometry previously set in
-     * {@link CarouselController#setDefaultGeometry(int)} or
-     * {@link CarouselController#setLoadingGeometry(int)} or
-     * {@link CarouselController#setGeometryForItem(int,Mesh)}.
-     *
-     * @param configs An array, each element of which corresponds to an ordered mesh primitive
-     */
-    public void setStoreConfigs(int configs[]) {
-        mStoreConfigs = configs;
-        if (mRenderScript != null) {
-            mRenderScript.setStoreConfigs(configs);
-        }
-    }
-}
diff --git a/carousel/java/com/android/ex/carousel/CarouselRS.java b/carousel/java/com/android/ex/carousel/CarouselRS.java
deleted file mode 100644
index 9d78d09..0000000
--- a/carousel/java/com/android/ex/carousel/CarouselRS.java
+++ /dev/null
@@ -1,949 +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.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Rect;
-import android.renderscript.*;
-import static android.renderscript.Element.*;
-import android.renderscript.Program.TextureType;
-import android.renderscript.RenderScript.RSMessageHandler;
-import android.util.Log;
-
-/**
- * This is a support class for Carousel renderscript.  It handles most of the low-level interactions
- * with Renderscript as well as dispatching events.
- *
- */
-public class CarouselRS  {
-    private static final int DEFAULT_VISIBLE_SLOTS = 1;
-    private static final int DEFAULT_CARD_COUNT = 0;
-    private static final int DEFAULT_ROW_COUNT = 1;
-
-    // Client messages *** THIS LIST MUST MATCH THOSE IN carousel.rs ***
-    public static final int CMD_CARD_SELECTED = 100;
-    public static final int CMD_DETAIL_SELECTED = 105;
-    public static final int CMD_CARD_LONGPRESS = 110;
-    public static final int CMD_REQUEST_TEXTURE = 200;
-    public static final int CMD_INVALIDATE_TEXTURE = 210;
-    public static final int CMD_REQUEST_GEOMETRY = 300;
-    public static final int CMD_INVALIDATE_GEOMETRY = 310;
-    public static final int CMD_ANIMATION_STARTED = 400;
-    public static final int CMD_ANIMATION_FINISHED = 500;
-    public static final int CMD_REQUEST_DETAIL_TEXTURE = 600;
-    public static final int CMD_INVALIDATE_DETAIL_TEXTURE = 610;
-    public static final int CMD_PING = 1000; // for debugging
-
-    // Drag models *** THIS LIST MUST MATCH THOSE IN carousel.rs ***
-    public static final int DRAG_MODEL_SCREEN_DELTA = 0;
-    public static final int DRAG_MODEL_PLANE = 1;
-    public static final int DRAG_MODEL_CYLINDER_INSIDE = 2;
-    public static final int DRAG_MODEL_CYLINDER_OUTSIDE = 3;
-
-    public static final int FILL_DIRECTION_CCW = +1;
-    public static final int FILL_DIRECTION_CW = -1;
-
-    private static final String TAG = "CarouselRS";
-    private static final int DEFAULT_SLOT_COUNT = 10;
-    private static final Allocation.MipmapControl MIPMAP =
-        Allocation.MipmapControl.MIPMAP_NONE;
-    private static final boolean DBG = false;
-
-    private RenderScriptGL mRS;
-    private Resources mRes;
-    private ScriptC_carousel mScript;
-    private ScriptField_Card mCards;
-    private ScriptField_FragmentShaderConstants_s mFSConst;
-    private ScriptField_ProgramStore_s mProgramStoresCard;
-    private ProgramFragment mSingleTextureFragmentProgram;
-    private ProgramFragment mSingleTextureBlendingFragmentProgram;
-    private ProgramFragment mMultiTextureFragmentProgram;
-    private ProgramFragment mMultiTextureBlendingFragmentProgram;
-    private ProgramVertex mVertexProgram;
-    private ProgramRaster mRasterProgram;
-    private Allocation[] mAllocationPool;
-    private boolean mForceBlendCardsWithZ;
-    private int mVisibleSlots;
-    private int mRowCount;
-    private int mPrefetchCardCount;
-    private CarouselCallback mCallback;
-    private float[] mEyePoint = new float[] { 2.0f, 0.0f, 0.0f };
-    private float[] mAtPoint = new float[] { 0.0f, 0.0f, 0.0f };
-    private float[] mUp = new float[] { 0.0f, 1.0f, 0.0f };
-
-    private static final String mSingleTextureShader = new String(
-            "varying vec2 varTex0;" +
-            "void main() {" +
-            "vec2 t0 = varTex0.xy;" +
-            "vec4 col = texture2D(UNI_Tex0, t0);" +
-            "gl_FragColor = col; " +
-            "}");
-
-    private static final String mSingleTextureBlendingShader = new String(
-            "varying vec2 varTex0;" +
-            "void main() {" +
-            "vec2 t0 = varTex0.xy;" +
-            "vec4 col = texture2D(UNI_Tex0, t0);" +
-            "gl_FragColor = col * UNI_overallAlpha; " +
-            "}");
-
-    private static final String mMultiTextureShader = new String(
-            "varying vec2 varTex0;" +
-            "void main() {" +
-            "vec2 t0 = varTex0.xy;" +
-            "vec4 col = texture2D(UNI_Tex0, t0);" +
-            "vec4 col2 = texture2D(UNI_Tex1, t0);" +
-            "gl_FragColor = mix(col, col2, UNI_fadeAmount);}");
-
-    private static final String mMultiTextureBlendingShader = new String(
-            "varying vec2 varTex0;" +
-            "void main() {" +
-            "vec2 t0 = varTex0.xy;" +
-            "vec4 col = texture2D(UNI_Tex0, t0);" +
-            "vec4 col2 = texture2D(UNI_Tex1, t0);" +
-            "gl_FragColor = mix(col, col2, UNI_fadeAmount) * UNI_overallAlpha;" +
-            "}"
-    );
-
-    public static interface CarouselCallback {
-        /**
-         * Called when a card is selected
-         * @param n the id of the card
-         */
-        void onCardSelected(int n);
-
-        /**
-         * Called when the detail texture for a card is tapped
-         * @param n the id of the card
-         * @param x how far the user tapped from the left edge of the card, in pixels
-         * @param y how far the user tapped from the top edge of the card, in pixels
-         */
-        void onDetailSelected(int n, int x, int y);
-
-        /**
-         * Called when a card is long-pressed
-         * @param n the id of the card
-         * @param touchPosition position of where the user pressed, in screen coordinates
-         * @param detailCoordinates position of detail texture, in screen coordinates
-         */
-        void onCardLongPress(int n, int touchPosition[], Rect detailCoordinates);
-
-        /**
-         * Called when texture is needed for card n.  This happens when the given card becomes
-         * visible.
-         * @param n the id of the card
-         */
-        void onRequestTexture(int n);
-
-        /**
-         * Called when a texture is no longer needed for card n.  This happens when the card
-         * goes out of view.
-         * @param n the id of the card
-         */
-        void onInvalidateTexture(int n);
-
-        /**
-         * Called when detail texture is needed for card n.  This happens when the given card
-         * becomes visible.
-         * @param n the id of the card
-         */
-        void onRequestDetailTexture(int n);
-
-        /**
-         * Called when a detail texture is no longer needed for card n.  This happens when the card
-         * goes out of view.
-         * @param n the id of the card
-         */
-        void onInvalidateDetailTexture(int n);
-
-        /**
-         * Called when geometry is needed for card n.
-         * @param n the id of the card.
-         */
-        void onRequestGeometry(int n);
-
-        /**
-         * Called when geometry is no longer needed for card n. This happens when the card goes
-         * out of view.
-         * @param n the id of the card
-         */
-        void onInvalidateGeometry(int n);
-
-        /**
-         * Called when card animation (e.g. a fling) has started.
-         */
-        void onAnimationStarted();
-
-        /**
-         * Called when card animation has stopped.
-         * @param carouselRotationAngle the angle of rotation, in radians, at which the animation
-         * stopped.
-         */
-        void onAnimationFinished(float carouselRotationAngle);
-    };
-
-    private RSMessageHandler mRsMessage = new RSMessageHandler() {
-        public void run() {
-            if (mCallback == null) return;
-            switch (mID) {
-                case CMD_CARD_SELECTED:
-                    mCallback.onCardSelected(mData[0]);
-                    break;
-
-                case CMD_DETAIL_SELECTED:
-                    mCallback.onDetailSelected(mData[0], mData[1], mData[2]);
-                    break;
-
-                case CMD_CARD_LONGPRESS:
-                    int touchPosition[] = { mData[1], mData[2] };
-                    Rect detailCoordinates = new Rect(mData[3], mData[4], mData[5], mData[6]);
-                    mCallback.onCardLongPress(mData[0], touchPosition, detailCoordinates);
-                    break;
-
-                case CMD_REQUEST_TEXTURE:
-                    mCallback.onRequestTexture(mData[0]);
-                    break;
-
-                case CMD_INVALIDATE_TEXTURE:
-                    setTexture(mData[0], null);
-                    mCallback.onInvalidateTexture(mData[0]);
-                    break;
-
-                case CMD_REQUEST_DETAIL_TEXTURE:
-                    mCallback.onRequestDetailTexture(mData[0]);
-                    break;
-
-                case CMD_INVALIDATE_DETAIL_TEXTURE:
-                    setDetailTexture(mData[0], 0.0f, 0.0f, 0.0f, 0.0f, null);
-                    mCallback.onInvalidateDetailTexture(mData[0]);
-                    break;
-
-                case CMD_REQUEST_GEOMETRY:
-                    mCallback.onRequestGeometry(mData[0]);
-                    break;
-
-                case CMD_INVALIDATE_GEOMETRY:
-                    setGeometry(mData[0], null);
-                    mCallback.onInvalidateGeometry(mData[0]);
-                    break;
-
-                case CMD_ANIMATION_STARTED:
-                    mCallback.onAnimationStarted();
-                    break;
-
-                case CMD_ANIMATION_FINISHED:
-                    mCallback.onAnimationFinished(Float.intBitsToFloat(mData[0]));
-                    break;
-
-                case CMD_PING:
-                    if (DBG) Log.v(TAG, "PING...");
-                    break;
-
-                default:
-                    Log.e(TAG, "Unknown RSMessage: " + mID);
-            }
-        }
-    };
-
-    public CarouselRS(RenderScriptGL rs, Resources res, int resId) {
-        mRS = rs;
-        mRes = res;
-
-        // create the script object
-        mScript = new ScriptC_carousel(mRS, mRes, resId);
-        mRS.setMessageHandler(mRsMessage);
-        initProgramStore();
-        initFragmentProgram();
-        initRasterProgram();
-        initVertexProgram();
-        setSlotCount(DEFAULT_SLOT_COUNT);
-        setVisibleSlots(DEFAULT_VISIBLE_SLOTS);
-        setRowCount(DEFAULT_ROW_COUNT);
-        createCards(DEFAULT_CARD_COUNT);
-        setStartAngle(0.0f);
-        setCarouselRotationAngle(0.0f);
-        setRadius(1.0f);
-        setLookAt(mEyePoint, mAtPoint, mUp);
-        setRadius(20.0f);
-        // Fov: 25
-    }
-
-    public void setLookAt(float[] eye, float[] at, float[] up) {
-        for (int i = 0; i < 3; i++) {
-            mEyePoint[i] = eye[i];
-            mAtPoint[i] = at[i];
-            mUp[i] = up[i];
-        }
-        mScript.invoke_lookAt(eye[0], eye[1], eye[2], at[0], at[1], at[2], up[0], up[1], up[2]);
-    }
-
-    public void setRadius(float radius) {
-        mScript.invoke_setRadius(radius);
-    }
-
-    public void setCardRotation(float cardRotation) {
-        mScript.set_cardRotation(cardRotation);
-    }
-
-    public void setCardsFaceTangent(boolean faceTangent) {
-        mScript.set_cardsFaceTangent(faceTangent);
-    }
-
-    public void setSwaySensitivity(float swaySensitivity) {
-        mScript.set_swaySensitivity(swaySensitivity);
-    }
-
-    public void setFrictionCoefficient(float frictionCoeff) {
-        mScript.set_frictionCoeff(frictionCoeff);
-    }
-
-    public void setDragFactor(float dragFactor) {
-        mScript.set_dragFactor(dragFactor);
-    }
-
-    public void setDragModel(int model) {
-        mScript.set_dragModel(model);
-    }
-
-    public void setFillDirection(int direction) {
-        mScript.set_fillDirection(direction);
-    }
-
-    private Matrix4f matrixFromFloat(float[] matrix) {
-        int dimensions;
-        if (matrix == null || matrix.length == 0) {
-          dimensions = 0;
-        } else if (matrix.length == 16) {
-          dimensions = 4;
-        } else if (matrix.length == 9) {
-          dimensions = 3;
-        } else {
-          throw new IllegalArgumentException("matrix length not 0,9 or 16");
-        }
-
-        Matrix4f rsMatrix = new Matrix4f();  // initialized as identity.
-        for (int i = 0; i < dimensions; i++) {
-            for (int j = 0; j < dimensions; j++) {
-                rsMatrix.set(i, j, matrix[i*dimensions + j]);
-            }
-        }
-
-        return rsMatrix;
-    }
-
-    public void setDefaultCardMatrix(float[] matrix) {
-        mScript.set_defaultCardMatrix(matrixFromFloat(matrix));
-    }
-
-    private void initVertexProgram() {
-        ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS);
-        mVertexProgram = pvb.create();
-        ProgramVertexFixedFunction.Constants pva = new ProgramVertexFixedFunction.Constants(mRS);
-        ((ProgramVertexFixedFunction)mVertexProgram).bindConstants(pva);
-        Matrix4f proj = new Matrix4f();
-        proj.loadProjectionNormalized(1, 1);
-        pva.setProjection(proj);
-        mScript.set_vertexProgram(mVertexProgram);
-    }
-
-    private void initRasterProgram() {
-        ProgramRaster.Builder programRasterBuilder = new ProgramRaster.Builder(mRS);
-        mRasterProgram = programRasterBuilder.create();
-        //mRasterProgram.setCullMode(CullMode.NONE);
-        mScript.set_rasterProgram(mRasterProgram);
-    }
-
-    private void initFragmentProgram() {
-        //
-        // Single texture program
-        //
-        ProgramFragment.Builder pfbSingle = new ProgramFragment.Builder(mRS);
-        // Specify the resource that contains the shader string
-        pfbSingle.setShader(mSingleTextureShader);
-        // Tell the builder how many textures we have
-        pfbSingle.addTexture(Program.TextureType.TEXTURE_2D);
-        mSingleTextureFragmentProgram = pfbSingle.create();
-        // Bind the source of constant data
-        mSingleTextureFragmentProgram.bindSampler(Sampler.CLAMP_LINEAR(mRS), 0);
-
-        //
-        // Single texture program, plus blending
-        //
-        mFSConst = new ScriptField_FragmentShaderConstants_s(mRS, 1);
-        mScript.bind_shaderConstants(mFSConst);
-        ProgramFragment.Builder pfbSingleBlend = new ProgramFragment.Builder(mRS);
-        // Specify the resource that contains the shader string
-        pfbSingleBlend.setShader(mSingleTextureBlendingShader);
-        // Tell the builder how many textures we have
-        pfbSingleBlend.addTexture(Program.TextureType.TEXTURE_2D);
-        // Define the constant input layout
-        pfbSingleBlend.addConstant(mFSConst.getAllocation().getType());
-        mSingleTextureBlendingFragmentProgram = pfbSingleBlend.create();
-        // Bind the source of constant data
-        mSingleTextureBlendingFragmentProgram.bindConstants(mFSConst.getAllocation(), 0);
-        mSingleTextureBlendingFragmentProgram.bindSampler(Sampler.CLAMP_LINEAR(mRS), 0);
-
-        //
-        // Multi texture program
-        //
-        ProgramFragment.Builder pfbMulti = new ProgramFragment.Builder(mRS);
-        // Specify the resource that contains the shader string
-        pfbMulti.setShader(mMultiTextureShader);
-        // Tell the builder how many textures we have
-        pfbMulti.addTexture(Program.TextureType.TEXTURE_2D);
-        pfbMulti.addTexture(Program.TextureType.TEXTURE_2D);
-        // Define the constant input layout
-        pfbMulti.addConstant(mFSConst.getAllocation().getType());
-        mMultiTextureFragmentProgram = pfbMulti.create();
-        // Bind the source of constant data
-        mMultiTextureFragmentProgram.bindConstants(mFSConst.getAllocation(), 0);
-        mMultiTextureFragmentProgram.bindSampler(Sampler.CLAMP_LINEAR(mRS), 0);
-        mMultiTextureFragmentProgram.bindSampler(Sampler.CLAMP_LINEAR(mRS), 1);
-
-        //
-        // Multi texture program, plus blending
-        //
-        ProgramFragment.Builder pfbMultiBlend = new ProgramFragment.Builder(mRS);
-        // Specify the resource that contains the shader string
-        pfbMultiBlend.setShader(mMultiTextureBlendingShader);
-        // Tell the builder how many textures we have
-        pfbMultiBlend.addTexture(Program.TextureType.TEXTURE_2D);
-        pfbMultiBlend.addTexture(Program.TextureType.TEXTURE_2D);
-        // Define the constant input layout
-        pfbMultiBlend.addConstant(mFSConst.getAllocation().getType());
-        mMultiTextureBlendingFragmentProgram = pfbMultiBlend.create();
-        // Bind the source of constant data
-        mMultiTextureBlendingFragmentProgram.bindConstants(mFSConst.getAllocation(), 0);
-        mMultiTextureBlendingFragmentProgram.bindSampler(Sampler.CLAMP_LINEAR(mRS), 0);
-        mMultiTextureBlendingFragmentProgram.bindSampler(Sampler.CLAMP_LINEAR(mRS), 1);
-
-        mScript.set_linearClamp(Sampler.CLAMP_LINEAR(mRS));
-        mScript.set_singleTextureFragmentProgram(mSingleTextureFragmentProgram);
-        mScript.set_singleTextureBlendingFragmentProgram(mSingleTextureBlendingFragmentProgram);
-        mScript.set_multiTextureFragmentProgram(mMultiTextureFragmentProgram);
-        mScript.set_multiTextureBlendingFragmentProgram(mMultiTextureBlendingFragmentProgram);
-    }
-
-    private void initProgramStore() {
-        resizeProgramStoresCard(1);
-
-        final boolean dither = true;
-        final ProgramStore.DepthFunc depthFunc = mForceBlendCardsWithZ ?
-                ProgramStore.DepthFunc.LESS : ProgramStore.DepthFunc.ALWAYS;
-
-        // Background: Alpha disabled, depth optional
-        mScript.set_programStoreBackground(new ProgramStore.Builder(mRS)
-            .setBlendFunc(ProgramStore.BlendSrcFunc.ONE, ProgramStore.BlendDstFunc.ZERO)
-            .setDitherEnabled(dither)
-            .setDepthFunc(depthFunc)
-            .setDepthMaskEnabled(mForceBlendCardsWithZ)
-            .create());
-
-        // Card: Alpha enabled, depth optional
-        setProgramStoreCard(0, new ProgramStore.Builder(mRS)
-            .setBlendFunc(ProgramStore.BlendSrcFunc.ONE,
-                ProgramStore.BlendDstFunc.ONE_MINUS_SRC_ALPHA)
-            .setDitherEnabled(dither)
-            .setDepthFunc(depthFunc)
-            .setDepthMaskEnabled(mForceBlendCardsWithZ)
-            .create());
-
-        // Detail: Alpha enabled, depth disabled
-        mScript.set_programStoreDetail(new ProgramStore.Builder(mRS)
-            .setBlendFunc(ProgramStore.BlendSrcFunc.ONE,
-                ProgramStore.BlendDstFunc.ONE_MINUS_SRC_ALPHA)
-            .setDitherEnabled(dither)
-            .setDepthFunc(ProgramStore.DepthFunc.ALWAYS)
-            .setDepthMaskEnabled(false)
-            .create());
-    }
-
-    public void createCards(int count)
-    {
-        // Because RenderScript can't have allocations with 0 dimensions, we always create
-        // an allocation of at least one card. This relies on invoke_createCards() to keep
-        // track of when the allocation is not valid.
-        if (mCards != null && count > 0) {
-            // resize the array
-            int oldSize = mCards.getAllocation().getType().getX();
-            mCards.resize(count);
-            mScript.invoke_createCards(oldSize, count);
-        } else {
-            // create array from scratch
-            mCards = new ScriptField_Card(mRS, count > 0 ? count : 1);
-            mScript.bind_cards(mCards);
-            mScript.invoke_createCards(0, count);
-        }
-    }
-
-    public void setVisibleSlots(int count)
-    {
-        mVisibleSlots = count;
-        mScript.set_visibleSlotCount(count);
-    }
-
-    public void setVisibleDetails(int count) {
-        mScript.set_visibleDetailCount(count);
-    }
-
-    public void setRowCount(int count) {
-        mRowCount = count;
-        mScript.set_rowCount(count);
-    }
-
-    public void setRowSpacing(float spacing) {
-        mScript.set_rowSpacing(spacing);
-    }
-
-    public void setOverscrollSlots(float slots) {
-        mScript.set_overscrollSlots(slots);
-    }
-
-    public void setFirstCardTop(boolean first) {
-        mScript.set_firstCardTop(first);
-    }
-
-    public void setPrefetchCardCount(int count) {
-        mPrefetchCardCount = count;
-        mScript.set_prefetchCardCount(count);
-    }
-
-    public void setDetailTextureAlignment(int alignment) {
-        mScript.set_detailTextureAlignment(alignment);
-    }
-
-    private void resizeProgramStoresCard(int count) {
-        // enableResize works around a Renderscript bug that keeps resizes from being propagated.
-        // TODO(jshuma): Remove enableResize once the Renderscript bug is fixed
-        final boolean enableResize = false;
-
-        if (mProgramStoresCard != null && enableResize) {
-            int newSize = count > 0 ? count : 1;
-            mProgramStoresCard.resize(newSize);
-        } else {
-            mProgramStoresCard = new ScriptField_ProgramStore_s(mRS, count > 0 ? count : 1);
-            mScript.bind_programStoresCard(mProgramStoresCard);
-        }
-    }
-
-    private void setProgramStoreCard(int n, ProgramStore programStore) {
-        ScriptField_ProgramStore_s.Item item = mProgramStoresCard.get(n);
-        if (item == null) {
-            item = new ScriptField_ProgramStore_s.Item();
-        }
-        item.programStore = programStore;
-        mProgramStoresCard.set(item, n, false);
-        mScript.invoke_setProgramStoresCard(n, programStore);
-    }
-
-    public void setStoreConfigs(int configs[]) {
-        if (configs == null) {
-            initProgramStore();
-            return;
-        }
-
-        final int count = configs.length;
-
-        resizeProgramStoresCard(count);
-        for (int i=0; i<count; ++i) {
-            final int config = configs[i];
-
-            final boolean alpha = (config & CarouselController.STORE_CONFIG_ALPHA) != 0;
-            final boolean depthReads = (config & CarouselController.STORE_CONFIG_DEPTH_READS) != 0;
-            final boolean depthWrites =
-                    (config & CarouselController.STORE_CONFIG_DEPTH_WRITES) != 0;
-
-            final boolean dither = true;
-            final ProgramStore.BlendDstFunc dstFunc = alpha ?
-                    ProgramStore.BlendDstFunc.ONE_MINUS_SRC_ALPHA :
-                    ProgramStore.BlendDstFunc.ZERO;
-            final ProgramStore.DepthFunc depthFunc = depthReads ?
-                    ProgramStore.DepthFunc.LESS :
-                    ProgramStore.DepthFunc.ALWAYS;
-
-            final ProgramStore ps = new ProgramStore.Builder(mRS)
-                    .setBlendFunc(ProgramStore.BlendSrcFunc.ONE, dstFunc)
-                    .setDitherEnabled(dither)
-                    .setDepthFunc(depthFunc)
-                    .setDepthMaskEnabled(depthWrites)
-                    .create();
-
-            setProgramStoreCard(i, ps);
-        }
-    }
-
-    /**
-     * Sets whether the background texture and default card geometry are to be drawn with respect
-     * to the depth buffer (both reading from it and writing to it).
-     *
-     * This method is a specialization of functionality that can be done with greater flexibility
-     * by setStoreConfigs. Calling setForceBlendCardsWithZ() after calling setStoreConfigs()
-     * results in the values set in setStoreConfigs() being discarded.
-     *
-     * @param enabled true to read from and write to the depth buffer, false to ignore it
-     */
-    public void setForceBlendCardsWithZ(boolean enabled) {
-        mForceBlendCardsWithZ = enabled;
-        initProgramStore();
-    }
-
-    public void setDrawRuler(boolean drawRuler) {
-        mScript.set_drawRuler(drawRuler);
-    }
-
-    public void setDefaultBitmap(Bitmap bitmap)
-    {
-        mScript.set_defaultTexture(allocationFromBitmap(bitmap, MIPMAP));
-    }
-
-    public void setLoadingBitmap(Bitmap bitmap)
-    {
-        mScript.set_loadingTexture(allocationFromBitmap(bitmap, MIPMAP));
-    }
-
-    public void setDefaultGeometry(Mesh mesh)
-    {
-        mScript.set_defaultGeometry(mesh);
-    }
-
-    public void setLoadingGeometry(Mesh mesh)
-    {
-        mScript.set_loadingGeometry(mesh);
-    }
-
-    public void setStartAngle(float theta)
-    {
-        mScript.set_startAngle(theta);
-    }
-
-    public void setCarouselRotationAngle(float theta) {
-        mScript.invoke_setCarouselRotationAngle(theta);
-    }
-
-    public void setCarouselRotationAngle(float endAngle, int milliseconds, int interpolationMode,
-            float maxAnimatedArc) {
-        mScript.invoke_setCarouselRotationAngle2(endAngle, milliseconds, interpolationMode,
-                maxAnimatedArc);
-    }
-
-    public void setCallback(CarouselCallback callback)
-    {
-        mCallback = callback;
-    }
-
-    private Allocation allocationFromBitmap(Bitmap bitmap, Allocation.MipmapControl mipmap)
-    {
-        if (bitmap == null) return null;
-        Allocation allocation = Allocation.createFromBitmap(mRS, bitmap,
-                mipmap, Allocation.USAGE_GRAPHICS_TEXTURE);
-        return allocation;
-    }
-
-    private Allocation allocationFromPool(int n, Bitmap bitmap, Allocation.MipmapControl mipmap)
-    {
-        int count = (mVisibleSlots + 2*mPrefetchCardCount) * mRowCount;
-        if (mAllocationPool == null || mAllocationPool.length != count) {
-            Allocation[] tmp = new Allocation[count];
-            int oldsize = mAllocationPool == null ? 0 : mAllocationPool.length;
-            for (int i = 0; i < Math.min(count, oldsize); i++) {
-                tmp[i] = mAllocationPool[i];
-            }
-            mAllocationPool = tmp;
-        }
-        Allocation allocation = mAllocationPool[n % count];
-        if (allocation == null) {
-            allocation = allocationFromBitmap(bitmap, mipmap);
-            mAllocationPool[n % count]  = allocation;
-        } else if (bitmap != null) {
-            if (bitmap.getWidth() == allocation.getType().getX()
-                && bitmap.getHeight() == allocation.getType().getY()) {
-                allocation.copyFrom(bitmap);
-            } else {
-                Log.v(TAG, "Warning, bitmap has different size. Taking slow path");
-                allocation = allocationFromBitmap(bitmap, mipmap);
-                mAllocationPool[n % count]  = allocation;
-            }
-        }
-        return allocation;
-    }
-
-    private ScriptField_Card.Item getCard(int n) {
-        ScriptField_Card.Item item;
-        try {
-            item = mCards.get(n);
-        }
-        catch (ArrayIndexOutOfBoundsException e) {
-            if (DBG) Log.v(TAG, "getCard(): no item at index " + n);
-            item = null;
-        }
-        return item;
-    }
-
-    private ScriptField_Card.Item getOrCreateCard(int n) {
-        ScriptField_Card.Item item = getCard(n);
-        if (item == null) {
-            if (DBG) Log.v(TAG, "getOrCreateCard(): no item at index " + n + "; creating new");
-            item = new ScriptField_Card.Item();
-        }
-        return item;
-    }
-
-    private void setCard(int n, ScriptField_Card.Item item) {
-        try {
-            mCards.set(item, n, false); // This is primarily used for reference counting.
-        }
-        catch (ArrayIndexOutOfBoundsException e) {
-            // The specified index didn't exist. This can happen when a stale invalidate
-            // request outlived an array resize request. Something might be getting dropped,
-            // but there's not much we can do about this at this point to recover.
-            Log.w(TAG, "setCard(" + n + "): Texture " + n + " doesn't exist");
-        }
-    }
-
-    public void setTexture(int n, Bitmap bitmap)
-    {
-        if (n < 0) throw new IllegalArgumentException("Index cannot be negative");
-
-        synchronized(this) {
-            ScriptField_Card.Item item = getOrCreateCard(n);
-            if (bitmap != null) {
-                item.texture = allocationFromPool(n, bitmap, MIPMAP);
-            } else {
-                if (item.texture != null) {
-                    if (DBG) Log.v(TAG, "unloading texture " + n);
-                    item.texture = null;
-                }
-            }
-            setCard(n, item);
-            mScript.invoke_setTexture(n, item.texture);
-        }
-    }
-
-    void setDetailTexture(int n, float offx, float offy, float loffx, float loffy, Bitmap bitmap)
-    {
-        if (n < 0) throw new IllegalArgumentException("Index cannot be negative");
-
-        synchronized(this) {
-            ScriptField_Card.Item item = getOrCreateCard(n);
-            float width = 0.0f;
-            float height = 0.0f;
-            if (bitmap != null) {
-                item.detailTexture = allocationFromBitmap(bitmap, MIPMAP);
-                width = bitmap.getWidth();
-                height = bitmap.getHeight();
-            } else {
-                if (item.detailTexture != null) {
-                    if (DBG) Log.v(TAG, "unloading detail texture " + n);
-                    // Don't wait for GC to free native memory.
-                    // Only works if textures are not shared.
-                    item.detailTexture.destroy();
-                    item.detailTexture = null;
-                }
-            }
-            setCard(n, item);
-            mScript.invoke_setDetailTexture(n, offx, offy, loffx, loffy, item.detailTexture);
-        }
-    }
-
-    void invalidateTexture(int n, boolean eraseCurrent)
-    {
-        if (n < 0) throw new IllegalArgumentException("Index cannot be negative");
-
-        synchronized(this) {
-            ScriptField_Card.Item item = getCard(n);
-            if (item == null) {
-                // This card was never created, so there's nothing to invalidate.
-                return;
-            }
-            if (eraseCurrent && item.texture != null) {
-                if (DBG) Log.v(TAG, "unloading texture " + n);
-                // Don't wait for GC to free native memory.
-                // Only works if textures are not shared.
-                item.texture.destroy();
-                item.texture = null;
-            }
-            setCard(n, item);
-            mScript.invoke_invalidateTexture(n, eraseCurrent);
-        }
-    }
-
-    void invalidateDetailTexture(int n, boolean eraseCurrent)
-    {
-        if (n < 0) throw new IllegalArgumentException("Index cannot be negative");
-
-        synchronized(this) {
-            ScriptField_Card.Item item = getCard(n);
-            if (item == null) {
-                // This card was never created, so there's nothing to invalidate.
-                return;
-            }
-            if (eraseCurrent && item.detailTexture != null) {
-                if (DBG) Log.v(TAG, "unloading detail texture " + n);
-                // Don't wait for GC to free native memory.
-                // Only works if textures are not shared.
-                item.detailTexture.destroy();
-                item.detailTexture = null;
-            }
-            setCard(n, item);
-            mScript.invoke_invalidateDetailTexture(n, eraseCurrent);
-        }
-    }
-
-    public void setGeometry(int n, Mesh geometry)
-    {
-        if (n < 0) throw new IllegalArgumentException("Index cannot be negative");
-
-        synchronized(this) {
-            final boolean mipmap = false;
-            ScriptField_Card.Item item = getOrCreateCard(n);
-            if (geometry != null) {
-                item.geometry = geometry;
-            } else {
-                if (DBG) Log.v(TAG, "unloading geometry " + n);
-                if (item.geometry != null) {
-                    // item.geometry.destroy();
-                    item.geometry = null;
-                }
-            }
-            setCard(n, item);
-            mScript.invoke_setGeometry(n, item.geometry);
-        }
-    }
-
-    public void setMatrix(int n, float[] matrix) {
-        if (n < 0) throw new IllegalArgumentException("Index cannot be negative");
-
-        synchronized(this) {
-            final boolean mipmap = false;
-            ScriptField_Card.Item item = getOrCreateCard(n);
-            if (matrix != null) {
-                item.matrix = matrixFromFloat(matrix);
-            } else {
-                if (DBG) Log.v(TAG, "unloading matrix " + n);
-                item.matrix = null;
-            }
-            setCard(n, item);
-            mScript.invoke_setMatrix(n, item.matrix);
-        }
-    }
-
-    public void setBackgroundColor(Float4 color) {
-        mScript.set_backgroundColor(color);
-    }
-
-    public void setBackgroundTexture(Bitmap bitmap) {
-        Allocation texture = null;
-        if (bitmap != null) {
-            texture = Allocation.createFromBitmap(mRS, bitmap,
-                    MIPMAP, Allocation.USAGE_GRAPHICS_TEXTURE);
-        }
-        mScript.set_backgroundTexture(texture);
-    }
-
-    public void setDetailLineTexture(Bitmap bitmap) {
-        Allocation texture = null;
-        if (bitmap != null) {
-            texture = Allocation.createFromBitmap(mRS, bitmap,
-                    MIPMAP, Allocation.USAGE_GRAPHICS_TEXTURE);
-        }
-        mScript.set_detailLineTexture(texture);
-    }
-
-    public void setDetailLoadingTexture(Bitmap bitmap) {
-        Allocation texture = null;
-        if (bitmap != null) {
-            texture = Allocation.createFromBitmap(mRS, bitmap,
-                    MIPMAP, Allocation.USAGE_GRAPHICS_TEXTURE);
-        }
-        mScript.set_detailLoadingTexture(texture);
-    }
-
-    public void pauseRendering() {
-        // Used to update multiple states at once w/o redrawing for each.
-        mRS.bindRootScript(null);
-    }
-
-    public void resumeRendering() {
-        mRS.bindRootScript(mScript);
-    }
-
-    public void doLongPress() {
-        mScript.invoke_doLongPress();
-    }
-
-    public void doMotion(float x, float y, long t) {
-        mScript.invoke_doMotion(x, y, t);
-    }
-
-    public void doStart(float x, float y, long t) {
-        mScript.invoke_doStart(x, y, t);
-    }
-
-    public void doStop(float x, float y, long t) {
-        mScript.invoke_doStop(x, y, t);
-    }
-
-    public void setSlotCount(int n) {
-        mScript.set_slotCount(n);
-    }
-
-    public void setRezInCardCount(float alpha) {
-        mScript.set_rezInCardCount(alpha);
-    }
-
-    public void setFadeInDuration(long t) {
-        mScript.set_fadeInDuration((int)t); // TODO: Remove cast when RS supports exporting longs
-    }
-
-    public void setCardCreationFadeDuration(long t) {
-        mScript.set_cardCreationFadeDuration((int)t);
-    }
-
-    private Element elementForBitmap(Bitmap bitmap, Bitmap.Config defaultConfig) {
-        Bitmap.Config config = bitmap.getConfig();
-        if (config == null) {
-            config = defaultConfig;
-        }
-        if (config == Bitmap.Config.ALPHA_8) {
-            return A_8(mRS);
-        } else if (config == Bitmap.Config.RGB_565) {
-            return RGB_565(mRS);
-        } else if (config == Bitmap.Config.ARGB_4444) {
-            return RGBA_4444(mRS);
-        } else if (config == Bitmap.Config.ARGB_8888) {
-            return RGBA_8888(mRS);
-        } else {
-            throw new IllegalArgumentException("Unknown configuration");
-        }
-    }
-
-    public Mesh loadGeometry(int resId) {
-        if (resId == 0) {
-          return null;
-        }
-        FileA3D model = FileA3D.createFromResource(mRS, mRes, resId);
-        if (model == null) {
-          return null;
-        }
-        FileA3D.IndexEntry entry = model.getIndexEntry(0);
-        if(entry == null || entry.getEntryType() != FileA3D.EntryType.MESH) {
-            return null;
-        }
-        return (Mesh) entry.getObject();
-    }
-}
diff --git a/carousel/java/com/android/ex/carousel/CarouselView.java b/carousel/java/com/android/ex/carousel/CarouselView.java
deleted file mode 100644
index 25c7366..0000000
--- a/carousel/java/com/android/ex/carousel/CarouselView.java
+++ /dev/null
@@ -1,605 +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.graphics.Bitmap;
-import android.renderscript.Float4;
-import android.renderscript.Mesh;
-import android.renderscript.RSSurfaceView;
-import android.renderscript.RenderScriptGL;
-import android.util.AttributeSet;
-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 CarouselView extends RSSurfaceView {
-    private static final boolean USE_DEPTH_BUFFER = true;
-    private static final String TAG = "CarouselView";
-    private CarouselRS mRenderScript;
-    private RenderScriptGL mRS;
-    private Context mContext;
-    private boolean mTracking;
-
-    CarouselController mController;
-
-    // Drag relative to x coordinate of motion on screen
-    public static final int DRAG_MODEL_SCREEN_DELTA = CarouselRS.DRAG_MODEL_SCREEN_DELTA;
-    // Drag relative to projected point on plane of carousel
-    public static final int DRAG_MODEL_PLANE = CarouselRS.DRAG_MODEL_PLANE;
-    // Drag relative to projected point on inside (far point) of cylinder centered around carousel
-    public static final int DRAG_MODEL_CYLINDER_INSIDE = CarouselRS.DRAG_MODEL_CYLINDER_INSIDE;
-    // Drag relative to projected point on outside (near point) of cylinder centered around carousel
-    public static final int DRAG_MODEL_CYLINDER_OUTSIDE = CarouselRS.DRAG_MODEL_CYLINDER_OUTSIDE;
-
-    // Draw cards counterclockwise around the carousel
-    public static final int FILL_DIRECTION_CCW = CarouselRS.FILL_DIRECTION_CCW;
-    // Draw cards clockwise around the carousel
-    public static final int FILL_DIRECTION_CW = CarouselRS.FILL_DIRECTION_CW;
-
-    // Note: remember to update carousel.rs when changing the values below
-    public static class InterpolationMode {
-        /** y= x **/
-        public static final int LINEAR = 0;
-        /** The quadratic curve y= 1 - (1 - x)^2 moves quickly towards the target
-         * while decelerating constantly. **/
-        public static final int DECELERATE_QUADRATIC = 1;
-        /** The cubic curve y= (3-2x)*x^2 gradually accelerates at the origin,
-         * and decelerates near the target. **/
-        public static final int ACCELERATE_DECELERATE_CUBIC = 2;
-    }
-
-    // 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 CarouselView(Context context) {
-        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 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 = createRenderScriptGL(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);
-        // setZOrderOnTop(true);
-        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(resId);
-    }
-
-    /**
-     * Set the geometry for a given item.
-     * @param n
-     * @param mesh
-     */
-    public void setGeometryForItem(int n, Mesh mesh) {
-        mController.setGeometryForItem(n, mesh);
-    }
-
-    /**
-     * Set the matrix for a given item.
-     * @param n
-     * @param matrix the requested matrix; null to just use the default
-     */
-    public void setMatrixForItem(int n, float[] matrix) {
-        mController.setMatrixForItem(n, matrix);
-    }
-
-    /**
-     * 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);
-    }
-
-    /**
-     * Sets the number of rows of cards to show in each slot.
-     */
-    public void setRowCount(int n) {
-        mController.setRowCount(n);
-    }
-
-    /**
-     * Sets the spacing between each row of cards when rowCount > 1.
-     */
-    public void setRowSpacing(float s) {
-        mController.setRowSpacing(s);
-    }
-
-    /**
-     * Sets the position of the first card when rowCount > 1.
-     */
-    public void setFirstCardTop(boolean f) {
-        mController.setFirstCardTop(f);
-    }
-
-    /**
-     * Sets the amount of allowed overscroll (in slots)
-     */
-    public void setOverscrollSlots(float slots) {
-        mController.setOverscrollSlots(slots);
-    }
-
-    /**
-     * 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 depth is enabled while blending. Generally, this is discouraged because
-     * it causes bad artifacts. Careful attention to geometry and alpha transparency of
-     * textures can mitigate much of this. For example, geometry for an item must be drawn
-     * back-to-front if any edges overlap.
-     *
-     * @param enabled True to enable depth while blending, and false to disable it.
-     */
-    public void setForceBlendCardsWithZ(boolean enabled) {
-        mController.setForceBlendCardsWithZ(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. If something other than
-     * simple planar geometry is used, consider enabling depth test with
-     * {@link CarouselView#setForceBlendCardsWithZ(boolean)}
-     *
-     * @param resId
-     */
-    public void setDefaultGeometry(int resId) {
-        mController.setDefaultGeometry(resId);
-    }
-
-    /**
-     * Sets the matrix used to transform card geometries.  By default, this
-     * is the identity matrix, but you can specify a different matrix if you
-     * want to scale, translate and / or rotate the card before drawing.
-     *
-     * @param matrix array of 9 or 16 floats representing a 3x3 or 4x4 matrix,
-     * or null as a shortcut for an identity matrix.
-     */
-    public void setDefaultCardMatrix(float[] matrix) {
-        mController.setDefaultCardMatrix(matrix);
-    }
-
-    /**
-     * 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. If something other than
-     * simple planar geometry is used, consider enabling depth test with
-     * {@link CarouselView#setForceBlendCardsWithZ(boolean)}
-     *
-     * @param resId
-     */
-    public void setLoadingGeometry(int resId) {
-        mController.setLoadingGeometry(resId);
-    }
-
-    /**
-     * 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 setDragModel(int model) {
-        mController.setDragModel(model);
-    }
-
-    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;
-            destroyRenderScriptGL();
-        }
-        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();
-
-        if (mRenderScript == null) {
-            return true;
-        }
-
-        switch (action) {
-            case MotionEvent.ACTION_DOWN:
-                mTracking = true;
-                mController.onTouchStarted(event.getX(), event.getY(), event.getEventTime());
-                break;
-
-            case MotionEvent.ACTION_MOVE:
-                if (mTracking) {
-                    for (int i = 0; i < event.getHistorySize(); i++) {
-                        mController.onTouchMoved(event.getHistoricalX(i), event.getHistoricalY(i),
-                                event.getHistoricalEventTime(i));
-                    }
-                    mController.onTouchMoved(event.getX(), event.getY(), event.getEventTime());
-                }
-                break;
-
-            case MotionEvent.ACTION_UP:
-                mController.onTouchStopped(event.getX(), event.getY(), event.getEventTime());
-                mTracking = false;
-                break;
-        }
-
-        return true;
-    }
-}
diff --git a/carousel/java/com/android/ex/carousel/CarouselViewHelper.java b/carousel/java/com/android/ex/carousel/CarouselViewHelper.java
deleted file mode 100644
index ef05ba9..0000000
--- a/carousel/java/com/android/ex/carousel/CarouselViewHelper.java
+++ /dev/null
@@ -1,305 +0,0 @@
-package com.android.ex.carousel;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Matrix;
-import android.graphics.Rect;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.Message;
-import android.renderscript.Matrix4f;
-import android.renderscript.Mesh;
-import android.util.Log;
-
-import com.android.ex.carousel.CarouselRS.CarouselCallback;
-
-/**
- * CarouselViewHelper wraps all of the threading and event handling of the CarouselView,
- * providing a simpler interface.  Most users will just need to implement a handful of
- * methods to get an application working.
- *
- */
-public class CarouselViewHelper implements CarouselCallback {
-    private static final String TAG = "CarouselViewHelper";
-    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;
-    private static final int SET_MATRIX_N = 4;
-
-    // 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 CarouselView 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 = new Matrix4f(); }
-        public TextureParameters(Matrix4f _matrix) { matrix = _matrix; }
-        public Matrix4f 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(CarouselView carouselView) {
-        mCarouselView = carouselView;
-        mCarouselView.setCallback(this);
-    }
-
-    public CarouselViewHelper(Context context, CarouselView carouselView) {
-        this(context);
-        setCarouselView(carouselView);
-    }
-
-    public CarouselViewHelper(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();
-                }
-
-                TextureParameters params = getTextureParameters(id);
-                if (params != null) {
-                    mSyncHandler.obtainMessage(SET_MATRIX_N, id, 0,
-                            params.matrix.getArray()).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;
-
-                case SET_MATRIX_N:
-                    mCarouselView.setMatrixForItem(id, (float[]) 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 onDetailSelected(int n, int x, int y) {
-        if (DBG) Log.v(TAG, "onDetailSelected(" + n + ", " + x + ", " + y + ")");
-    }
-
-    public void onCardLongPress(int n, int touchPosition[], Rect detailCoordinates) {
-        if (DBG) Log.v(TAG, "onCardLongPress(" + n + ", (" + touchPosition + "), (" +
-                detailCoordinates +") )");
-    }
-
-    public void onAnimationStarted() {
-
-    }
-
-    public void onAnimationFinished(float carouselRotationAngle) {
-
-    }
-
-    public void onResume() {
-        mCarouselView.resume();
-    }
-
-    public void onPause() {
-        mCarouselView.pause();
-    }
-
-    public void onDestroy() {
-        mHandlerThread.quit();
-    }
-
-    protected Handler getAsyncHandler() {
-        return mAsyncHandler;
-    }
-
-    protected CarouselView getCarouselView() {
-        return mCarouselView;
-    }
-}
diff --git a/carousel/java/com/android/ex/carousel/CarouselViewUtilities.java b/carousel/java/com/android/ex/carousel/CarouselViewUtilities.java
deleted file mode 100644
index 8b53734..0000000
--- a/carousel/java/com/android/ex/carousel/CarouselViewUtilities.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.android.ex.carousel;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.media.MediaScannerConnection;
-import android.os.Environment;
-import android.util.Log;
-
-public class CarouselViewUtilities {
-    /**
-     * Debug utility to write the given bitmap to a file.
-     *
-     * @param context calling context
-     * @param bitmap the bitmap to write
-     * @param filename the name of the file to write
-     * @return
-     */
-    public static boolean writeBitmapToFile(Context context, Bitmap bitmap, String filename) {
-        File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
-        File file = new File(path, filename);
-        boolean result = false;
-        try {
-            path.mkdirs();
-            OutputStream os = new FileOutputStream(file);
-            MediaScannerConnection.scanFile(context, new String[] { file.toString() }, null, null);
-            bitmap.compress(Bitmap.CompressFormat.PNG, 100, os);
-            result = true;
-        } catch (IOException e) {
-            Log.w("ExternalStorage", "Error writing " + file, e);
-        }
-        return result;
-    }
-
-}
diff --git a/carousel/java/com/android/ex/carousel/carousel.rs b/carousel/java/com/android/ex/carousel/carousel.rs
deleted file mode 100644
index e4dcc65..0000000
--- a/carousel/java/com/android/ex/carousel/carousel.rs
+++ /dev/null
@@ -1,1884 +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.
- */
-
-#pragma version(1)
-#pragma rs java_package_name(com.android.ex.carousel);
-#pragma rs set_reflect_license()
-
-#include "rs_graphics.rsh"
-
-typedef struct __attribute__((aligned(4))) Card {
-    // *** Update initCard if you add/remove fields here.
-    rs_allocation texture; // basic card texture
-    rs_allocation detailTexture; // screen-aligned detail texture
-    float2 detailTextureOffset; // offset to add, in screen coordinates
-    float2 detailLineOffset; // offset to add to detail line, in screen coordinates
-    float2 detailTexturePosition[2]; // screen coordinates of detail texture, computed at draw time
-    rs_mesh geometry;
-    rs_matrix4x4 matrix; // custom transform for this card/geometry
-    int textureState;  // whether or not the primary card texture is loaded.
-    int detailTextureState; // whether or not the detail for the card is loaded.
-    int geometryState; // whether or not geometry is loaded
-    int cardVisible; // not bool because of packing bug?
-    int detailVisible; // not bool because of packing bug?
-    int shouldPrefetch; // not bool because of packing bug?
-    int64_t textureTimeStamp; // time when this texture was last updated, in ms
-    int64_t detailTextureTimeStamp; // time when this texture was last updated, in ms
-    int64_t geometryTimeStamp; // time when the card itself was last updated, in ms
-} Card_t;
-
-typedef struct Ray_s {
-    float3 position;
-    float3 direction;
-} Ray;
-
-typedef struct Plane_s {
-    float3 point;
-    float3 normal;
-    float constant;
-} Plane;
-
-typedef struct Cylinder_s {
-    float3 center; // center of a y-axis-aligned infinite cylinder
-    float radius;
-} Cylinder;
-
-typedef struct PerspectiveCamera_s {
-    float3 from;
-    float3 at;
-    float3 up;
-    float  fov;
-    float  aspect;
-    float  near;
-    float  far;
-} PerspectiveCamera;
-
-typedef struct ProgramStore_s {
-    rs_program_store programStore;
-} ProgramStore_t;
-
-typedef struct FragmentShaderConstants_s {
-    float fadeAmount;
-    float overallAlpha;
-} FragmentShaderConstants;
-
-// Request states. Used for loading 3D object properties from the Java client.
-// Typical properties: texture, geometry and matrices.
-enum {
-    STATE_INVALID = 0, // item hasn't been loaded
-    STATE_LOADING, // we've requested an item but are waiting for it to load
-    STATE_STALE, // we have an old item, but should request an update
-    STATE_UPDATING, // we've requested an update, and will display the old one in the meantime
-    STATE_LOADED // item was delivered
-};
-
-// Interpolation modes ** THIS LIST MUST MATCH THOSE IN CarouselView.java ***
-enum {
-    INTERPOLATION_LINEAR = 0,
-    INTERPOLATION_DECELERATE_QUADRATIC = 1,
-    INTERPOLATION_ACCELERATE_DECELERATE_CUBIC = 2,
-};
-
-// Detail texture alignments ** THIS LIST MUST MATCH THOSE IN CarouselView.java ***
-enum {
-    /** Detail is centered vertically with respect to the card **/
-    CENTER_VERTICAL = 1,
-    /** Detail is aligned with the top edge of the carousel view **/
-    VIEW_TOP = 1 << 1,
-    /** Detail is aligned with the bottom edge of the carousel view (not yet implemented) **/
-    VIEW_BOTTOM = 1 << 2,
-    /** Detail is positioned above the card (not yet implemented) **/
-    ABOVE = 1 << 3,
-    /** Detail is positioned below the card **/
-    BELOW = 1 << 4,
-    /** Mask that selects those bits that control vertical alignment **/
-    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.
-     */
-    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.
-     */
-    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)
-     */
-    RIGHT = 1 << 10,
-    /** Mask that selects those bits that control horizontal alignment **/
-    HORIZONTAL_ALIGNMENT_MASK = 0xff00,
-};
-
-// Client messages *** THIS LIST MUST MATCH THOSE IN CarouselRS.java. ***
-static const int CMD_CARD_SELECTED = 100;
-static const int CMD_DETAIL_SELECTED = 105;
-static const int CMD_CARD_LONGPRESS = 110;
-static const int CMD_REQUEST_TEXTURE = 200;
-static const int CMD_INVALIDATE_TEXTURE = 210;
-static const int CMD_REQUEST_GEOMETRY = 300;
-static const int CMD_INVALIDATE_GEOMETRY = 310;
-static const int CMD_ANIMATION_STARTED = 400;
-static const int CMD_ANIMATION_FINISHED = 500;
-static const int CMD_REQUEST_DETAIL_TEXTURE = 600;
-static const int CMD_INVALIDATE_DETAIL_TEXTURE = 610;
-static const int CMD_PING = 1000;
-
-// Drag model *** THIS LIST MUST MATCH THOSE IN CarouselRS.java. ***
-static const int DRAG_MODEL_SCREEN_DELTA = 0; // Drag relative to x coordinate of motion vector
-static const int DRAG_MODEL_PLANE = 1; // Drag relative to projected point on plane of carousel
-static const int DRAG_MODEL_CYLINDER_INSIDE = 2; // Drag relative to point on inside of cylinder
-static const int DRAG_MODEL_CYLINDER_OUTSIDE = 3; // Drag relative to point on outside of cylinder
-
-// Constants
-static const int ANIMATION_DELAY_TIME = 125; // hold off scale animation until this time
-static const int ANIMATION_SCALE_UP_TIME = 200; // Time it takes to animate selected card, in ms
-static const int ANIMATION_SCALE_DOWN_TIME = 200; // Time it takes to animate selected card, in ms
-static const float3 SELECTED_SCALE_FACTOR = { 0.1f, 0.1f, 0.1f }; // increase by this %
-static const int VELOCITY_HISTORY_MAX = 10; // # recent velocity samples used to calculate average
-static const int VISIBLE_SLOT_PADDING = 2;  // # slots to draw on either side of visible slots
-
-// Constants affecting tilt overscroll.  Some of these should be parameters.
-static const int TILT_SLOT_NUMBER = 5;
-static const float TILT_MIN_ANGLE = M_PI / 315.0f;
-static const float TILT_MAX_BIAS = M_PI / 8.0f;
-static const float TILT_MAX_ANGLE = M_PI / 8.0f;
-static const float MAX_DELTA_BIAS = 0.008f;
-
-// Debug flags
-const bool debugCamera = false; // dumps ray/camera coordinate stuff
-const bool debugSelection = false; // logs selection events
-const bool debugTextureLoading = false; // for debugging texture load/unload
-const bool debugGeometryLoading = false; // for debugging geometry load/unload
-const bool debugDetails = false; // for debugging detail texture geometry
-const bool debugRendering = false; // flashes display when the frame changes
-const bool debugRays = false; // shows visual depiction of hit tests, See renderWithRays().
-
-// Exported variables. These will be reflected to Java set_* variables.
-Card_t *cards; // array of cards to draw
-float startAngle; // position of initial card, in radians
-int slotCount; // number of positions where a card can be
-int cardCount; // number of cards in stack
-int programStoresCardCount; // number of program fragment stores
-int visibleSlotCount; // number of visible slots (for culling)
-int visibleDetailCount; // number of visible detail textures to show
-int prefetchCardCount; // how many cards to keep in memory
-int detailTextureAlignment; // How to align detail texture with respect to card
-bool drawRuler; // whether to draw a ruler from the card to the detail texture
-float radius; // carousel radius. Cards will be centered on a circle with this radius
-float cardRotation; // rotation of card in XY plane relative to Z=1
-bool cardsFaceTangent; // whether cards are rotated to face along a tangent to the circle
-float swaySensitivity; // how much to rotate cards in relation to the rotation velocity
-float frictionCoeff; // how much to slow down the carousel over time
-float dragFactor; // a scale factor for how sensitive the carousel is to user dragging
-int fadeInDuration; // amount of time (in ms) for smoothly switching out textures
-int cardCreationFadeDuration; // amount of time (in ms) to fade while initially showing a card
-float rezInCardCount; // this controls how rapidly distant card textures will be rez-ed in
-float detailFadeRate; // rate at which details fade as they move into the distance
-float4 backgroundColor;
-int rowCount;  // number of rows of cards in a given slot, default 1
-float rowSpacing;  // spacing between rows of cards
-bool firstCardTop; // set true for first card on top row when multiple rows used
-float overscrollSlots; // amount of allowed overscroll (in slots)
-
-int dragModel = DRAG_MODEL_SCREEN_DELTA;
-int fillDirection; // the order in which to lay out cards: +1 for CCW (default), -1 for CW
-ProgramStore_t *programStoresCard;
-rs_program_store programStoreBackground;
-rs_program_store programStoreDetail;
-rs_program_fragment singleTextureFragmentProgram;
-rs_program_fragment singleTextureBlendingFragmentProgram;
-rs_program_fragment multiTextureFragmentProgram;
-rs_program_fragment multiTextureBlendingFragmentProgram;
-rs_program_vertex vertexProgram;
-rs_program_raster rasterProgram;
-rs_allocation defaultTexture; // shown when no other texture is assigned
-rs_allocation loadingTexture; // progress texture (shown when app is fetching the texture)
-rs_allocation backgroundTexture; // drawn behind everything, if set
-rs_allocation detailLineTexture; // used to draw detail line (as a quad, of course)
-rs_allocation detailLoadingTexture; // used when detail texture is loading
-rs_mesh defaultGeometry; // shown when no geometry is loaded
-rs_mesh loadingGeometry; // shown when geometry is loading
-rs_matrix4x4 defaultCardMatrix;
-rs_matrix4x4 projectionMatrix;
-rs_matrix4x4 modelviewMatrix;
-FragmentShaderConstants* shaderConstants;
-rs_sampler linearClamp;
-
-// Local variables
-static float bias; // rotation bias, in radians. Used for animation and dragging.
-static float overscrollBias; // Track overscroll bias separately for tilt effect.
-static bool updateCamera;    // force a recompute of projection and lookat matrices
-static const float FLT_MAX = 1.0e37;
-static int animatedSelection = -1;
-static int currentFirstCard = -1;
-static int64_t touchTime = -1; // time of first touch (see doStart())
-static int64_t releaseTime = 0L; // when touch was released
-static float touchBias = 0.0f; // bias on first touch
-static float2 touchPosition; // position of first touch, as defined by last call to doStart(x,y)
-static float velocity = 0.0f;  // angular velocity in radians/s
-static bool isOverScrolling = false; // whether we're in the overscroll animation
-static bool isAutoScrolling = false; // whether we're in the autoscroll animation
-static bool isDragging = false; // true while the user is dragging the carousel
-static float selectionRadius = 50.0f; // movement greater than this will result in no selection
-static bool enableSelection = false; // enabled until the user drags outside of selectionRadius
-static float tiltAngle = 0.0f;
-
-// Default plane of the carousel. Used for angular motion estimation in view.
-static Plane carouselPlane = {
-       { 0.0f, 0.0f, 0.0f }, // point
-       { 0.0f, 1.0f, 0.0f }, // normal
-       0.0f // plane constant (= -dot(P, N))
-};
-
-static Cylinder carouselCylinder = {
-        {0.0f, 0.0f, 0.0f }, // center
-        1.0f // radius - update with carousel radius.
-};
-
-// Because allocations can't have 0 dimensions, we have to track whether or not
-// cards and program stores are valid separately.
-// TODO: Remove this dependency once allocations can have a zero dimension.
-static bool cardAllocationValid = false;
-static bool programStoresAllocationValid = false;
-
-// Default geometry when card.geometry is not set.
-static const float3 cardVertices[4] = {
-        { -1.0, -1.0, 0.0 },
-        { 1.0, -1.0, 0.0 },
-        { 1.0, 1.0, 0.0 },
-        {-1.0, 1.0, 0.0 }
-};
-
-// Default camera
-static PerspectiveCamera camera = {
-        {2,2,2}, // from
-        {0,0,0}, // at
-        {0,1,0}, // up
-        25.0f,   // field of view
-        1.0f,    // aspect
-        0.1f,    // near
-        100.0f   // far
-};
-
-// Forward references
-static int intersectGeometry(Ray* ray, float *bestTime);
-static int intersectDetailTexture(float x, float y, float2 *tapCoordinates);
-static bool __attribute__((overloadable))
-        makeRayForPixelAt(Ray* ray, PerspectiveCamera* cam, float x, float y);
-static bool __attribute__((overloadable))
-        makeRayForPixelAt(Ray* ray, rs_matrix4x4* model, rs_matrix4x4* proj, float x, float y);
-static float deltaTimeInSeconds(int64_t current);
-static bool rayPlaneIntersect(Ray* ray, Plane* plane, float* tout);
-static bool rayCylinderIntersect(Ray* ray, Cylinder* cylinder, float* tout);
-static void stopAutoscroll();
-static bool tiltOverscroll();
-
-void init() {
-    // initializers currently have a problem when the variables are exported, so initialize
-    // globals here.
-    if (debugTextureLoading) rsDebug("Renderscript: init()", 0);
-    startAngle = 0.0f;
-    slotCount = 10;
-    visibleSlotCount = 1;
-    visibleDetailCount = 3;
-    bias = 0.0f;
-    overscrollBias = 0.0f;
-    tiltAngle = 0.0f;
-    radius = carouselCylinder.radius = 1.0f;
-    cardRotation = 0.0f;
-    cardsFaceTangent = false;
-    updateCamera = true;
-    backgroundColor = (float4) { 0.0f, 0.0f, 0.0f, 1.0f };
-    cardAllocationValid = false;
-    programStoresAllocationValid = false;
-    cardCount = 0;
-    rowCount = 1;
-    rowSpacing = 0.0f;
-    firstCardTop = false;
-    fadeInDuration = 250;
-    rezInCardCount = 0.0f; // alpha will ramp to 1.0f over this many cards (0.0f means disabled)
-    detailFadeRate = 0.5f; // fade details over this many slot positions.
-    rsMatrixLoadIdentity(&defaultCardMatrix);
-}
-
-static void updateAllocationVars()
-{
-    // Cards
-    rs_allocation cardAlloc;
-    cardAlloc = rsGetAllocation(cards);
-    cardCount = (cardAllocationValid && rsIsObject(cardAlloc)) ? rsAllocationGetDimX(cardAlloc) : 0;
-
-    // Program stores
-    rs_allocation psAlloc;
-    psAlloc = rsGetAllocation(programStoresCard);
-    programStoresCardCount = (programStoresAllocationValid && rsIsObject(psAlloc) ?
-        rsAllocationGetDimX(psAlloc) : 0);
-}
-
-void setRadius(float rad)
-{
-    radius = carouselCylinder.radius = rad;
-}
-
-static void initCard(Card_t* card)
-{
-    // Object refs are always initilized cleared.
-    static const float2 zero = {0.0f, 0.0f};
-    card->detailTextureOffset = zero;
-    card->detailLineOffset = zero;
-    rsMatrixLoad(&card->matrix, &defaultCardMatrix);
-    card->textureState = STATE_INVALID;
-    card->detailTextureState = STATE_INVALID;
-    card->geometryState = STATE_INVALID;
-    card->cardVisible = false;
-    card->detailVisible = false;
-    card->shouldPrefetch = false;
-    card->textureTimeStamp = 0;
-    card->detailTextureTimeStamp = 0;
-    card->geometryTimeStamp = rsUptimeMillis();
-}
-
-void createCards(int start, int total)
-{
-    if (!cardAllocationValid) {
-        // If the allocation is invalid, it contains a single place-holder
-        // card that has not yet been initialized (see CarouselRS.createCards).
-        // Here we ensure that it is initialized when growing the total.
-        start = 0;
-    }
-    for (int k = start; k < total; k++) {
-        initCard(cards + k);
-    }
-
-    // Since allocations can't have 0-size, we track validity ourselves based on the call to
-    // this method.
-    cardAllocationValid = total > 0;
-
-    updateAllocationVars();
-}
-
-// Computes an alpha value for a card using elapsed time and constant fadeInDuration
-static float getAnimatedAlpha(int64_t startTime, int64_t currentTime, int64_t duration)
-{
-    double timeElapsed = (double) (currentTime - startTime); // in ms
-    double alpha = duration > 0 ? (double) timeElapsed / duration : 1.0;
-    return min(1.0f, (float) alpha);
-}
-
-// Returns total angle for given number of slots
-static float wedgeAngle(float slots)
-{
-    return slots * 2.0f * M_PI / slotCount;
-}
-
-// Return angle of slot in position p.
-static float slotPosition(int p)
-{
-    return startAngle + wedgeAngle(p) * fillDirection;
-}
-
-// Return angle for card in position p.
-static float cardPosition(int p)
-{
-    return bias + slotPosition(p / rowCount);
-}
-
-// Return the lowest possible bias value, based on the fill direction
-static float minimumBias()
-{
-    const int totalSlots = (cardCount + rowCount - 1) / rowCount;
-    return (fillDirection > 0) ?
-        -max(0.0f, wedgeAngle(totalSlots - visibleDetailCount)) :
-        wedgeAngle(0.0f);
-}
-
-// Return the highest possible bias value, based on the fill direction
-static float maximumBias()
-{
-    const int totalSlots = (cardCount + rowCount - 1) / rowCount;
-    return (fillDirection > 0) ?
-        wedgeAngle(0.0f) :
-        max(0.0f, wedgeAngle(totalSlots - visibleDetailCount));
-}
-
-
-// convert from carousel rotation angle (in card slot units) to radians.
-static float carouselRotationAngleToRadians(float carouselRotationAngle)
-{
-    return -wedgeAngle(carouselRotationAngle);
-}
-
-// convert from radians to carousel rotation angle (in card slot units).
-static float radiansToCarouselRotationAngle(float angle)
-{
-    return -angle * slotCount / ( 2.0f * M_PI );
-}
-
-// Set basic camera properties:
-//    from - position of the camera in x,y,z
-//    at - target we're looking at - used to compute view direction
-//    up - a normalized vector indicating up (typically { 0, 1, 0})
-//
-// NOTE: the view direction and up vector cannot be parallel/antiparallel with each other
-void lookAt(float fromX, float fromY, float fromZ,
-        float atX, float atY, float atZ,
-        float upX, float upY, float upZ)
-{
-    camera.from.x = fromX;
-    camera.from.y = fromY;
-    camera.from.z = fromZ;
-    camera.at.x = atX;
-    camera.at.y = atY;
-    camera.at.z = atZ;
-    camera.up.x = upX;
-    camera.up.y = upY;
-    camera.up.z = upZ;
-    updateCamera = true;
-}
-
-// Load a projection matrix for the given parameters.  This is equivalent to gluPerspective()
-static void loadPerspectiveMatrix(rs_matrix4x4* matrix, float fovy, float aspect, float near, float far)
-{
-    rsMatrixLoadIdentity(matrix);
-    float top = near * tan((float) (fovy * M_PI / 360.0f));
-    float bottom = -top;
-    float left = bottom * aspect;
-    float right = top * aspect;
-    rsMatrixLoadFrustum(matrix, left, right, bottom, top, near, far);
-}
-
-// Construct a matrix based on eye point, center and up direction. Based on the
-// man page for gluLookat(). Up must be normalized.
-static void loadLookatMatrix(rs_matrix4x4* matrix, float3 eye, float3 center, float3 up)
-{
-    float3 f = normalize(center - eye);
-    float3 s = normalize(cross(f, up));
-    float3 u = cross(s, f);
-    float m[16];
-    m[0] = s.x;
-    m[4] = s.y;
-    m[8] = s.z;
-    m[12] = 0.0f;
-    m[1] = u.x;
-    m[5] = u.y;
-    m[9] = u.z;
-    m[13] = 0.0f;
-    m[2] = -f.x;
-    m[6] = -f.y;
-    m[10] = -f.z;
-    m[14] = 0.0f;
-    m[3] = m[7] = m[11] = 0.0f;
-    m[15] = 1.0f;
-    rsMatrixLoad(matrix, m);
-    rsMatrixTranslate(matrix, -eye.x, -eye.y, -eye.z);
-}
-
-/*
- * Returns true if a state represents a texture that is loaded enough to draw
- */
-static bool textureEverLoaded(int state) {
-    return (state == STATE_LOADED) || (state == STATE_STALE) || (state == STATE_UPDATING);
-}
-
-void setTexture(int n, rs_allocation texture)
-{
-    if (n < 0 || n >= cardCount) return;
-    cards[n].texture = texture;
-    if (cards[n].textureState != STATE_STALE &&
-        cards[n].textureState != STATE_UPDATING) {
-        cards[n].textureTimeStamp = rsUptimeMillis();
-    }
-    cards[n].textureState = (texture.p != 0) ? STATE_LOADED : STATE_INVALID;
-}
-
-void setDetailTexture(int n, float offx, float offy, float loffx, float loffy, rs_allocation texture)
-{
-    if (n < 0 || n >= cardCount) return;
-    cards[n].detailTexture = texture;
-    if (cards[n].detailTextureState != STATE_STALE &&
-        cards[n].detailTextureState != STATE_UPDATING) {
-        cards[n].detailTextureTimeStamp = rsUptimeMillis();
-    }
-    cards[n].detailTextureOffset.x = offx;
-    cards[n].detailTextureOffset.y = offy;
-    cards[n].detailLineOffset.x = loffx;
-    cards[n].detailLineOffset.y = loffy;
-    cards[n].detailTextureState = (texture.p != 0) ? STATE_LOADED : STATE_INVALID;
-}
-
-void invalidateTexture(int n, bool eraseCurrent)
-{
-    if (n < 0 || n >= cardCount) return;
-    if (eraseCurrent) {
-        cards[n].textureState = STATE_INVALID;
-        rsClearObject(&cards[n].texture);
-    } else {
-        cards[n].textureState =
-            textureEverLoaded(cards[n].textureState) ? STATE_STALE : STATE_INVALID;
-    }
-}
-
-void invalidateDetailTexture(int n, bool eraseCurrent)
-{
-    if (n < 0 || n >= cardCount) return;
-    if (eraseCurrent) {
-        cards[n].detailTextureState = STATE_INVALID;
-        rsClearObject(&cards[n].detailTexture);
-    } else {
-        cards[n].detailTextureState =
-            textureEverLoaded(cards[n].detailTextureState) ? STATE_STALE : STATE_INVALID;
-    }
-}
-
-void setGeometry(int n, rs_mesh geometry)
-{
-    if (n < 0 || n >= cardCount) return;
-    cards[n].geometry = geometry;
-    if (cards[n].geometry.p != 0)
-        cards[n].geometryState = STATE_LOADED;
-    else
-        cards[n].geometryState = STATE_INVALID;
-    cards[n].geometryTimeStamp = rsUptimeMillis();
-}
-
-void setMatrix(int n, rs_matrix4x4 matrix) {
-    if (n < 0 || n >= cardCount) return;
-    cards[n].matrix = matrix;
-}
-
-void setProgramStoresCard(int n, rs_program_store programStore)
-{
-    programStoresCard[n].programStore = programStore;
-    programStoresAllocationValid = true;
-}
-
-void setCarouselRotationAngle(float carouselRotationAngle) {
-    bias = carouselRotationAngleToRadians(carouselRotationAngle);
-}
-
-// Gets animated scale value for current selected card.
-// If card is currently being animated, returns true,  otherwise returns false.
-static bool getAnimatedScaleForSelected(float3* scale)
-{
-    static const float3 one = { 1.0f, 1.0f, 1.0f };
-    static float fraction = 0.0f;
-    bool stillAnimating = false;
-    if (isDragging) {
-        // "scale up" animation
-        int64_t dt = rsUptimeMillis() - touchTime - ANIMATION_DELAY_TIME;
-        if (dt > 0L && enableSelection) {
-            float s = (float) dt / ANIMATION_SCALE_UP_TIME;
-            s = min(s, 1.0f);
-            fraction = max(s, fraction);
-        }
-        stillAnimating = dt < ANIMATION_SCALE_UP_TIME;
-    } else {
-        // "scale down" animation
-        int64_t dt = rsUptimeMillis() - releaseTime;
-        if (dt < ANIMATION_SCALE_DOWN_TIME) {
-            float s = 1.0f - ((float) dt / ANIMATION_SCALE_DOWN_TIME);
-            fraction = min(s, fraction);
-            stillAnimating = true;
-        } else {
-            fraction = 0.0f;
-        }
-    }
-    *scale = one + fraction * SELECTED_SCALE_FACTOR;
-    return stillAnimating; // still animating;
-}
-
-// The Verhulst logistic function: http://en.wikipedia.org/wiki/Logistic_function
-//    P(t) = 1 / (1 + e^(-t))
-// Parameter t: Any real number
-// Returns: A float in the range (0,1), with P(0.5)=0
-static float logistic(float t) {
-    return 1.f / (1.f + exp(-t));
-}
-
-static float getSwayAngleForVelocity(float v, bool enableSway)
-{
-    float sway = 0.0f;
-
-    if (enableSway) {
-        const float range = M_PI * 2./3.; // How far we can deviate from center, peak-to-peak
-        sway = range * (logistic(-v * swaySensitivity) - 0.5f);
-    }
-
-    return sway;
-}
-
-static float getCardTiltAngle(int i) {
-    i /= rowCount;
-    int totalSlots = (cardCount + rowCount - 1) / rowCount;
-    float tiltSlotNumber = TILT_SLOT_NUMBER;
-    float deltaTilt = tiltAngle / tiltSlotNumber;
-    float cardTiltAngle = 0;
-    if (tiltAngle > 0 && i < tiltSlotNumber) {
-        // Overscroll for the front cards.
-        cardTiltAngle = deltaTilt * (tiltSlotNumber - i);
-    } else if (tiltAngle < 0 && i > (totalSlots - tiltSlotNumber)) {
-        cardTiltAngle = deltaTilt * (i - totalSlots + tiltSlotNumber + 1);
-    }
-    return cardTiltAngle;
-}
-
-// Returns the vertical offset for a card in its slot,
-// depending on the number of rows configured.
-static float getVerticalOffsetForCard(int i) {
-   if (rowCount == 1) {
-       // fast path
-       return 0;
-   }
-   const float cardHeight = (cardVertices[3].y - cardVertices[0].y) *
-      rsMatrixGet(&defaultCardMatrix, 1, 1);
-   const float totalHeight = rowCount * (cardHeight + rowSpacing) - rowSpacing;
-   if (firstCardTop)
-      i = rowCount - (i % rowCount) - 1;
-   else
-      i = i % rowCount;
-   const float rowOffset = i * (cardHeight + rowSpacing);
-   return (cardHeight - totalHeight) / 2 + rowOffset;
-}
-
-/*
- * Composes a matrix for the given card.
- * matrix: The output matrix.
- * i: The card we're getting the matrix for.
- * enableSway: Whether to enable swaying. (We want it on for cards, and off for detail textures.)
- * enableCardMatrix: Whether to also consider the user-specified card matrix
- *
- * returns true if an animation is being applied to the given card
- */
-static bool getMatrixForCard(rs_matrix4x4* matrix, int i, bool enableSway, bool enableCardMatrix)
-{
-    float theta = cardPosition(i);
-    float swayAngle = getSwayAngleForVelocity(velocity, enableSway);
-    rsMatrixRotate(matrix, degrees(theta), 0, 1, 0);
-    rsMatrixTranslate(matrix, radius, getVerticalOffsetForCard(i), 0);
-    float tiltAngle = getCardTiltAngle(i);
-    float rotation = cardRotation + swayAngle + tiltAngle;
-    if (!cardsFaceTangent) {
-      rotation -= theta;
-    }
-    rsMatrixRotate(matrix, degrees(rotation), 0, 1, 0);
-    bool stillAnimating = false;
-    if (i == animatedSelection) {
-        float3 scale;
-        stillAnimating = getAnimatedScaleForSelected(&scale);
-        rsMatrixScale(matrix, scale.x, scale.y, scale.z);
-    }
-    // TODO(jshuma): Instead of ignoring this matrix for the detail texture, use card bounding box
-    if (enableCardMatrix) {
-        rsMatrixLoadMultiply(matrix, matrix, &cards[i].matrix);
-    }
-    return stillAnimating;
-}
-
-/*
- * Draws the requested mesh, with the appropriate program store in effect.
- */
-static void drawMesh(rs_mesh mesh)
-{
-    if (programStoresCardCount == 1) {
-        // Draw the entire mesh, with the only available program store
-        rsgBindProgramStore(programStoresCard[0].programStore);
-        rsgDrawMesh(mesh);
-    } else {
-        // Draw each primitive in the mesh with the corresponding program store
-        for (int i=0; i<programStoresCardCount; ++i) {
-            if (programStoresCard[i].programStore.p != 0) {
-                rsgBindProgramStore(programStoresCard[i].programStore);
-                rsgDrawMesh(mesh, i);
-            }
-        }
-    }
-}
-
-/*
- * Draws cards around the Carousel.
- * Returns true if we're still animating any property of the cards (e.g. fades).
- */
-static bool drawCards(int64_t currentTime)
-{
-    const float wedgeAngle = 2.0f * M_PI / slotCount;
-    const float endAngle = startAngle + visibleSlotCount * wedgeAngle;
-    bool stillAnimating = false;
-    for (int i = cardCount-1; i >= 0; i--) {
-        if (cards[i].cardVisible) {
-            // If this card was recently loaded, this will be < 1.0f until the animation completes
-            float animatedAlpha = getAnimatedAlpha(cards[i].textureTimeStamp, currentTime,
-                fadeInDuration);
-            float overallAlpha = getAnimatedAlpha(cards[i].geometryTimeStamp, currentTime,
-                cardCreationFadeDuration);
-            if (animatedAlpha < 1.0f || overallAlpha < 1.0f) {
-                stillAnimating = true;
-            }
-
-            // Compute fade out for cards in the distance
-            float positionAlpha;
-            if (rezInCardCount > 0.0f) {
-                positionAlpha = (endAngle - cardPosition(i)) / wedgeAngle;
-                positionAlpha = min(1.0f, positionAlpha / rezInCardCount);
-            } else {
-                positionAlpha = 1.0f;
-            }
-
-            // Set alpha for blending between the textures
-            shaderConstants->fadeAmount = min(1.0f, animatedAlpha * positionAlpha);
-            shaderConstants->overallAlpha = overallAlpha;
-            rsgAllocationSyncAll(rsGetAllocation(shaderConstants));
-
-            // Bind the appropriate shader network.  If there's no alpha blend, then
-            // switch to single shader for better performance.
-            const int state = cards[i].textureState;
-            bool loaded = textureEverLoaded(state) && rsIsObject(cards[i].texture);
-            if (shaderConstants->fadeAmount == 1.0f || shaderConstants->fadeAmount < 0.01f) {
-                if (overallAlpha < 1.0) {
-                    rsgBindProgramFragment(singleTextureBlendingFragmentProgram);
-                    rsgBindTexture(singleTextureBlendingFragmentProgram, 0,
-                            (loaded && shaderConstants->fadeAmount == 1.0f) ?
-                            cards[i].texture : loadingTexture);
-                } else {
-                    rsgBindProgramFragment(singleTextureFragmentProgram);
-                    rsgBindTexture(singleTextureFragmentProgram, 0,
-                            (loaded && shaderConstants->fadeAmount == 1.0f) ?
-                            cards[i].texture : loadingTexture);
-                }
-            } else {
-                if (overallAlpha < 1.0) {
-                    rsgBindProgramFragment(multiTextureBlendingFragmentProgram);
-                    rsgBindTexture(multiTextureBlendingFragmentProgram, 0, loadingTexture);
-                    rsgBindTexture(multiTextureBlendingFragmentProgram, 1, loaded ?
-                            cards[i].texture : loadingTexture);
-                } else {
-                    rsgBindProgramFragment(multiTextureFragmentProgram);
-                    rsgBindTexture(multiTextureFragmentProgram, 0, loadingTexture);
-                    rsgBindTexture(multiTextureFragmentProgram, 1, loaded ?
-                            cards[i].texture : loadingTexture);
-                }
-            }
-
-            // Draw geometry
-            rs_matrix4x4 matrix = modelviewMatrix;
-            stillAnimating |= getMatrixForCard(&matrix, i, true, true);
-            rsgProgramVertexLoadModelMatrix(&matrix);
-            if (cards[i].geometryState == STATE_LOADED && cards[i].geometry.p != 0) {
-                drawMesh(cards[i].geometry);
-            } else if (cards[i].geometryState == STATE_LOADING && loadingGeometry.p != 0) {
-                drawMesh(loadingGeometry);
-            } else if (defaultGeometry.p != 0) {
-                drawMesh(defaultGeometry);
-            } else {
-                // Draw place-holder geometry
-                rsgBindProgramStore(programStoresCard[0].programStore);
-                rsgDrawQuad(
-                    cardVertices[0].x, cardVertices[0].y, cardVertices[0].z,
-                    cardVertices[1].x, cardVertices[1].y, cardVertices[1].z,
-                    cardVertices[2].x, cardVertices[2].y, cardVertices[2].z,
-                    cardVertices[3].x, cardVertices[3].y, cardVertices[3].z);
-            }
-        }
-    }
-    return stillAnimating;
-}
-
-/**
- * Convert projection from normalized coordinates to pixel coordinates.
- *
- * @return True on success, false on failure.
- */
-static bool convertNormalizedToPixelCoordinates(float4 *screenCoord, float width, float height) {
-    // This is probably cheaper than pre-multiplying with another matrix.
-    if (screenCoord->w == 0.0f) {
-        rsDebug("Bad transform while converting from normalized to pixel coordinates: ",
-            screenCoord);
-        return false;
-    }
-    *screenCoord *= 1.0f / screenCoord->w;
-    screenCoord->x += 1.0f;
-    screenCoord->y += 1.0f;
-    screenCoord->z += 1.0f;
-    screenCoord->x = round(screenCoord->x * 0.5f * width);
-    screenCoord->y = round(screenCoord->y * 0.5f * height);
-    screenCoord->z = - 0.5f * screenCoord->z;
-    return true;
-}
-
-/*
- * Draws a screen-aligned card with the exact dimensions from the detail texture.
- * This is used to display information about the object being displayed.
- * Returns true if we're still animating any property of the cards (e.g. fades).
- */
-static bool drawDetails(int64_t currentTime)
-{
-    const float width = rsgGetWidth();
-    const float height = rsgGetHeight();
-
-    bool stillAnimating = false;
-
-    // We'll be drawing in screen space, sampled on pixel centers
-    rs_matrix4x4 projection, model;
-    rsMatrixLoadOrtho(&projection, 0.0f, width, 0.0f, height, 0.0f, 1.0f);
-    rsgProgramVertexLoadProjectionMatrix(&projection);
-    rsMatrixLoadIdentity(&model);
-    rsgProgramVertexLoadModelMatrix(&model);
-    updateCamera = true; // we messed with the projection matrix. Reload on next pass...
-
-    const float yPadding = 5.0f; // draw line this far (in pixels) away from top and geometry
-
-    // This can be done once...
-    rsgBindTexture(multiTextureFragmentProgram, 0, detailLoadingTexture);
-
-    const float wedgeAngle = 2.0f * M_PI / slotCount;
-    // Angle where details start fading from 1.0f
-    const float startDetailFadeAngle = startAngle + (visibleDetailCount - 1) * wedgeAngle;
-    // Angle where detail alpha is 0.0f
-    const float endDetailFadeAngle = startDetailFadeAngle + detailFadeRate * wedgeAngle;
-
-    for (int i = cardCount-1; i >= 0; --i) {
-        if (cards[i].cardVisible) {
-            const int state = cards[i].detailTextureState;
-            const bool isLoaded = textureEverLoaded(state);
-            if (isLoaded && cards[i].detailTexture.p != 0) {
-                const float lineWidth = rsAllocationGetDimX(detailLineTexture);
-
-                // Compute position in screen space of top corner or bottom corner of card
-                rsMatrixLoad(&model, &modelviewMatrix);
-                stillAnimating |= getMatrixForCard(&model, i, false, false);
-                rs_matrix4x4 matrix;
-                rsMatrixLoadMultiply(&matrix, &projectionMatrix, &model);
-
-                int indexLeft, indexRight;
-                float4 screenCoord;
-                if (detailTextureAlignment & BELOW) {
-                    indexLeft = 0;
-                    indexRight = 1;
-                } else {
-                    indexLeft = 3;
-                    indexRight = 2;
-                }
-                float4 screenCoordLeft = rsMatrixMultiply(&matrix, cardVertices[indexLeft]);
-                float4 screenCoordRight = rsMatrixMultiply(&matrix, cardVertices[indexRight]);
-                if (screenCoordLeft.w == 0.0f || screenCoordRight.w == 0.0f) {
-                    // this shouldn't happen
-                    rsDebug("Bad transform: ", screenCoord);
-                    continue;
-                }
-                if (detailTextureAlignment & CENTER_VERTICAL) {
-                    // If we're centering vertically, we'll need the other vertices too
-                    if (detailTextureAlignment & BELOW) {
-                        indexLeft = 3;
-                        indexRight = 2;
-                    } else {
-                        indexLeft = 0;
-                        indexRight = 1;
-                    }
-                    float4 otherScreenLeft = rsMatrixMultiply(&matrix, cardVertices[indexLeft]);
-                    float4 otherScreenRight = rsMatrixMultiply(&matrix, cardVertices[indexRight]);
-                    screenCoordRight.y = screenCoordLeft.y = (screenCoordLeft.y + screenCoordRight.y
-                        + otherScreenLeft.y + otherScreenRight.y) / 4.;
-                }
-                (void) convertNormalizedToPixelCoordinates(&screenCoordLeft, width, height);
-                (void) convertNormalizedToPixelCoordinates(&screenCoordRight, width, height);
-                if (debugDetails) {
-                    RS_DEBUG(screenCoordLeft);
-                    RS_DEBUG(screenCoordRight);
-                }
-                screenCoord = screenCoordLeft;
-                if (detailTextureAlignment & BELOW) {
-                    screenCoord.y = min(screenCoordLeft.y, screenCoordRight.y);
-                } else if (detailTextureAlignment & CENTER_VERTICAL) {
-                    screenCoord.y -= round(rsAllocationGetDimY(cards[i].detailTexture) / 2.0f);
-                }
-                if (detailTextureAlignment & CENTER_HORIZONTAL) {
-                    screenCoord.x += round((screenCoordRight.x - screenCoordLeft.x) / 2.0f -
-                        rsAllocationGetDimX(cards[i].detailTexture) / 2.0f);
-                }
-
-                // Compute alpha for gradually fading in details. Applied to both line and
-                // detail texture. TODO: use a separate background texture for line.
-                float animatedAlpha = getAnimatedAlpha(cards[i].detailTextureTimeStamp,
-                    currentTime, fadeInDuration);
-                if (animatedAlpha < 1.0f) {
-                    stillAnimating = true;
-                }
-
-                // Compute alpha based on position. We fade cards quickly so they cannot overlap
-                float positionAlpha = ((float)endDetailFadeAngle - cardPosition(i))
-                        / (endDetailFadeAngle - startDetailFadeAngle);
-                positionAlpha = max(0.0f, positionAlpha);
-                positionAlpha = min(1.0f, positionAlpha);
-
-                const float blendedAlpha = min(1.0f, animatedAlpha * positionAlpha);
-
-                if (blendedAlpha == 0.0f) {
-                    cards[i].detailVisible = false;
-                    continue; // nothing to draw
-                } else {
-                    cards[i].detailVisible = true;
-                }
-                if (blendedAlpha == 1.0f) {
-                    rsgBindProgramFragment(singleTextureFragmentProgram);
-                } else {
-                    rsgBindProgramFragment(multiTextureFragmentProgram);
-                }
-
-                // Set alpha for blending between the textures
-                shaderConstants->fadeAmount = blendedAlpha;
-                rsgAllocationSyncAll(rsGetAllocation(shaderConstants));
-
-                // Draw line from the card to the detail texture.
-                // The line is drawn from the top or bottom left of the card
-                // to either the top of the screen or the top of the detail
-                // texture, depending on detailTextureAlignment.
-                if (drawRuler) {
-                    float rulerTop;
-                    float rulerBottom;
-                    if (detailTextureAlignment & BELOW) {
-                        rulerTop = screenCoord.y;
-                        rulerBottom = 0;
-                    } else {
-                        rulerTop = height;
-                        rulerBottom = screenCoord.y;
-                    }
-                    const float halfWidth = lineWidth * 0.5f;
-                    const float x0 = trunc(cards[i].detailLineOffset.x + screenCoord.x - halfWidth);
-                    const float x1 = x0 + lineWidth;
-                    const float y0 = rulerBottom + yPadding;
-                    const float y1 = rulerTop - yPadding - cards[i].detailLineOffset.y;
-
-                    if (blendedAlpha == 1.0f) {
-                        rsgBindTexture(singleTextureFragmentProgram, 0, detailLineTexture);
-                    } else {
-                        rsgBindTexture(multiTextureFragmentProgram, 1, detailLineTexture);
-                    }
-                    rsgDrawQuad(x0, y0, screenCoord.z,  x1, y0, screenCoord.z,
-                            x1, y1, screenCoord.z,  x0, y1, screenCoord.z);
-                }
-
-                // Draw the detail texture next to it using the offsets provided.
-                const float textureWidth = rsAllocationGetDimX(cards[i].detailTexture);
-                const float textureHeight = rsAllocationGetDimY(cards[i].detailTexture);
-                const float offx = cards[i].detailTextureOffset.x;
-                const float offy = -cards[i].detailTextureOffset.y;
-                const float textureTop = (detailTextureAlignment & VIEW_TOP)
-                        ? height : screenCoord.y;
-                const float x0 = cards[i].detailLineOffset.x + screenCoord.x + offx;
-                const float x1 = cards[i].detailLineOffset.x + screenCoord.x + offx + textureWidth;
-                const float y0 = textureTop + offy - textureHeight - cards[i].detailLineOffset.y;
-                const float y1 = textureTop + offy - cards[i].detailLineOffset.y;
-                cards[i].detailTexturePosition[0].x = x0;
-                cards[i].detailTexturePosition[0].y = height - y1;
-                cards[i].detailTexturePosition[1].x = x1;
-                cards[i].detailTexturePosition[1].y = height - y0;
-
-                if (blendedAlpha == 1.0f) {
-                    rsgBindTexture(singleTextureFragmentProgram, 0, cards[i].detailTexture);
-                } else {
-                    rsgBindTexture(multiTextureFragmentProgram, 1, cards[i].detailTexture);
-                }
-                rsgDrawQuad(x0, y0, screenCoord.z,  x1, y0, screenCoord.z,
-                        x1, y1, screenCoord.z,  x0, y1, screenCoord.z);
-            }
-        }
-    }
-    return stillAnimating;
-}
-
-static void drawBackground()
-{
-    static bool toggle;
-    if (backgroundTexture.p != 0) {
-        rsgClearDepth(1.0f);
-        rs_matrix4x4 projection, model;
-        rsMatrixLoadOrtho(&projection, -1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f);
-        rsgProgramVertexLoadProjectionMatrix(&projection);
-        rsMatrixLoadIdentity(&model);
-        rsgProgramVertexLoadModelMatrix(&model);
-        rsgBindTexture(singleTextureFragmentProgram, 0, backgroundTexture);
-        float z = -0.9999f;
-        rsgDrawQuad(
-            cardVertices[0].x, cardVertices[0].y, z,
-            cardVertices[1].x, cardVertices[1].y, z,
-            cardVertices[2].x, cardVertices[2].y, z,
-            cardVertices[3].x, cardVertices[3].y, z);
-        updateCamera = true; // we mucked with the matrix.
-    } else {
-        rsgClearDepth(1.0f);
-        if (debugRendering) { // for debugging - flash the screen so we know we're still rendering
-            rsgClearColor(toggle ? backgroundColor.x : 1.0f,
-                        toggle ? backgroundColor.y : 0.0f,
-                        toggle ? backgroundColor.z : 0.0f,
-                        backgroundColor.w);
-            toggle = !toggle;
-        } else {
-           rsgClearColor(backgroundColor.x, backgroundColor.y, backgroundColor.z,
-                   backgroundColor.w);
-       }
-    }
-}
-
-static void updateCameraMatrix(float width, float height)
-{
-    float aspect = width / height;
-    if (aspect != camera.aspect || updateCamera) {
-        camera.aspect = aspect;
-        loadPerspectiveMatrix(&projectionMatrix, camera.fov, camera.aspect, camera.near, camera.far);
-        rsgProgramVertexLoadProjectionMatrix(&projectionMatrix);
-
-        loadLookatMatrix(&modelviewMatrix, camera.from, camera.at, camera.up);
-        rsgProgramVertexLoadModelMatrix(&modelviewMatrix);
-        updateCamera = false;
-    }
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Behavior/Physics
-////////////////////////////////////////////////////////////////////////////////////////////////////
-static int64_t lastTime = 0L; // keep track of how much time has passed between frames
-static float lastAngle = 0.0f;
-static float2 lastPosition;
-static bool animating = false;
-static float stopVelocity = 0.1f * M_PI / 180.0f; // slower than this: carousel stops
-static float selectionVelocity = 15.0f * M_PI / 180.0f; // faster than this: tap won't select
-static float velocityHistory[VELOCITY_HISTORY_MAX];
-static int velocityHistoryCount;
-static float mass = 5.0f; // kg
-
-static const float G = 9.80f; // gravity constant, in m/s
-static const float springConstant = 0.0f;
-
-// Computes a hit angle from the center of the carousel to a point on either a plane
-// or on a cylinder. If neither is hit, returns false.
-static bool hitAngle(float x, float y, float *angle)
-{
-    Ray ray;
-    makeRayForPixelAt(&ray, &camera, x, y);
-    float t = FLT_MAX;
-    if (dragModel == DRAG_MODEL_PLANE && rayPlaneIntersect(&ray, &carouselPlane, &t)) {
-        const float3 point = (ray.position + t*ray.direction);
-        const float3 direction = point - carouselPlane.point;
-        *angle = atan2(direction.x, direction.z);
-        if (debugSelection) rsDebug("Plane Angle = ", degrees(*angle));
-        return true;
-    } else if ((dragModel == DRAG_MODEL_CYLINDER_INSIDE || dragModel == DRAG_MODEL_CYLINDER_OUTSIDE)
-            && rayCylinderIntersect(&ray, &carouselCylinder, &t)) {
-        const float3 point = (ray.position + t*ray.direction);
-        const float3 direction = point - carouselCylinder.center;
-        *angle = atan2(direction.x, direction.z);
-        if (debugSelection) rsDebug("Cylinder Angle = ", degrees(*angle));
-        return true;
-    }
-    return false;
-}
-
-static float dragFunction(float x, float y)
-{
-    float result;
-    float angle;
-    if (hitAngle(x, y, &angle)) {
-        result = angle - lastAngle;
-        // Handle singularity where atan2 switches between +- PI
-        if (result < -M_PI) {
-            result += 2.0f * M_PI;
-        } else if (result > M_PI) {
-            result -= 2.0f * M_PI;
-        }
-        lastAngle = angle;
-    } else {
-        // If we didn't hit anything or drag model wasn't plane or cylinder, we use screen delta
-        result = dragFactor * ((x - lastPosition.x) / rsgGetWidth()) * M_PI;
-    }
-    return result;
-}
-
-static float deltaTimeInSeconds(int64_t current)
-{
-    return (lastTime > 0L) ? (float) (current - lastTime) / 1000.0f : 0.0f;
-}
-
-static int doSelection(float x, float y)
-{
-    Ray ray;
-    if (makeRayForPixelAt(&ray, &camera, x, y)) {
-        float bestTime = FLT_MAX;
-        return intersectGeometry(&ray, &bestTime);
-    }
-    return -1;
-}
-
-static void sendAnimationStarted() {
-    rsSendToClient(CMD_ANIMATION_STARTED);
-}
-
-static void sendAnimationFinished() {
-    float data[1];
-    data[0] = radiansToCarouselRotationAngle(bias);
-    rsSendToClient(CMD_ANIMATION_FINISHED, (int*) data, sizeof(data));
-}
-
-void doStart(float x, float y, long eventTime)
-{
-    touchPosition = lastPosition = (float2) { x, y };
-    lastAngle = hitAngle(x,y, &lastAngle) ? lastAngle : 0.0f;
-    enableSelection = fabs(velocity) < selectionVelocity;
-    velocity = 0.0f;
-    velocityHistory[0] = 0.0f;
-    velocityHistoryCount = 0;
-
-    releaseTime = lastTime; // used to disable scale down animation - any time in the past will do
-    touchTime = lastTime = eventTime;
-    touchBias = bias;
-    isDragging = true;
-    isOverScrolling = false;
-    tiltAngle = 0;
-    overscrollBias = bias;
-
-    animatedSelection = doSelection(x, y); // used to provide visual feedback on touch
-    stopAutoscroll();
-}
-
-static float computeAverageVelocityFromHistory()
-{
-    if (velocityHistoryCount > 0) {
-        const int count = min(VELOCITY_HISTORY_MAX, velocityHistoryCount);
-        float vsum = 0.0f;
-        for (int i = 0; i < count; i++) {
-            vsum += velocityHistory[i];
-        }
-        return vsum / count;
-    } else {
-        return 0.0f;
-    }
-}
-
-void doStop(float x, float y, long eventTime)
-{
-    updateAllocationVars();
-
-    releaseTime = rsUptimeMillis();
-
-    if (enableSelection) {
-        int data[3];
-        int selection;
-        float2 point;
-
-        if ((selection = intersectDetailTexture(x, y, &point)) != -1) {
-            if (debugSelection) rsDebug("Selected detail texture on doStop():", selection);
-            data[0] = selection;
-            data[1] = point.x;
-            data[2] = point.y;
-            rsSendToClientBlocking(CMD_DETAIL_SELECTED, data, sizeof(data));
-        }
-        else if ((selection = doSelection(x, y))!= -1) {
-            if (debugSelection) rsDebug("Selected item on doStop():", selection);
-            data[0] = selection;
-            rsSendToClientBlocking(CMD_CARD_SELECTED, data, sizeof(data));
-        }
-        animating = false;
-    } else {
-        velocity = computeAverageVelocityFromHistory();
-        if (fabs(velocity) > stopVelocity) {
-            animating = true;
-        }
-    }
-    enableSelection = false;
-    lastTime = eventTime;
-    isDragging = false;
-}
-
-void doLongPress()
-{
-    int64_t currentTime = rsUptimeMillis();
-    updateAllocationVars();
-    // Selection happens for most recent position detected in doMotion()
-    if (enableSelection && animatedSelection != -1) {
-        if (debugSelection) rsDebug("doLongPress(), selection = ", animatedSelection);
-        int data[7];
-        data[0] = animatedSelection;
-        data[1] = lastPosition.x;
-        data[2] = lastPosition.y;
-        data[3] = cards[animatedSelection].detailTexturePosition[0].x;
-        data[4] = cards[animatedSelection].detailTexturePosition[0].y;
-        data[5] = cards[animatedSelection].detailTexturePosition[1].x;
-        data[6] = cards[animatedSelection].detailTexturePosition[1].y;
-        rsSendToClientBlocking(CMD_CARD_LONGPRESS, data, sizeof(data));
-        enableSelection = false;
-    }
-    lastTime = rsUptimeMillis();
-}
-
-void doMotion(float x, float y, long eventTime)
-{
-    const float highBias = maximumBias();
-    const float lowBias = minimumBias();
-    float deltaOmega = dragFunction(x, y);
-    overscrollBias += deltaOmega;
-    overscrollBias = clamp(overscrollBias, lowBias - TILT_MAX_BIAS,
-            highBias + TILT_MAX_BIAS);
-    bias = clamp(overscrollBias, lowBias, highBias);
-    isOverScrolling = tiltOverscroll();
-
-    const float2 delta = (float2) { x, y } - touchPosition;
-    float distance = sqrt(dot(delta, delta));
-    bool inside = (distance < selectionRadius);
-    enableSelection &= inside;
-    lastPosition = (float2) { x, y };
-    float dt = deltaTimeInSeconds(eventTime);
-    if (dt > 0.0f) {
-        float v = deltaOmega / dt;
-        velocityHistory[velocityHistoryCount % VELOCITY_HISTORY_MAX] = v;
-        velocityHistoryCount++;
-    }
-    velocity = computeAverageVelocityFromHistory();
-    lastTime = eventTime;
-}
-
-bool tiltOverscroll() {
-    if (overscrollBias == bias) {
-        // No overscroll required.
-        return false;
-    }
-
-    // How much we deviate from the maximum bias.
-    float deltaBias = overscrollBias - bias;
-    // We clamped, that means we need overscroll.
-    tiltAngle = (deltaBias / TILT_MAX_BIAS)
-            * TILT_MAX_ANGLE * fillDirection;
-
-    return true;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Autoscroll Interpolation
-////////////////////////////////////////////////////////////////////////////////////////////////////
-static int64_t autoscrollStartTime = 0L; //tracks when we actually started interpolating
-static int64_t autoscrollDuration = 0L;  //in milli seconds
-static int autoscrollInterpolationMode = INTERPOLATION_LINEAR;
-
-static float autoscrollStopAngle = 0.0f;
-static float autoscrollStartAngle = 0.0f;
-
-void setCarouselRotationAngle2(
-    float endAngle,
-    int   milliseconds,
-    int   interpolationMode,
-    float maxAnimatedArc)
-{
-    float actualStart = radiansToCarouselRotationAngle(bias);
-
-    if (maxAnimatedArc > 0) {
-        //snap the current position to keep end - start under maxAnimatedArc
-        if (actualStart <= endAngle) {
-            if (actualStart < endAngle - maxAnimatedArc) {
-                actualStart = endAngle - maxAnimatedArc;
-            }
-        }
-        else {
-            if (actualStart > endAngle + maxAnimatedArc) {
-                actualStart = endAngle + maxAnimatedArc;
-            }
-        }
-    }
-
-    animating = true;
-    isAutoScrolling = true;
-    autoscrollDuration = milliseconds;
-    autoscrollInterpolationMode = interpolationMode;
-    autoscrollStartAngle = carouselRotationAngleToRadians(actualStart);
-    autoscrollStopAngle = carouselRotationAngleToRadians(endAngle);
-
-    //Make sure the start and stop angles are in the allowed range
-    const float highBias = maximumBias();
-    const float lowBias  = minimumBias();
-    autoscrollStartAngle = clamp(autoscrollStartAngle, lowBias, highBias);
-    autoscrollStopAngle  = clamp(autoscrollStopAngle, lowBias, highBias);
-
-    //stop other animation kinds
-    isOverScrolling = false;
-    velocity = 0.0f;
-}
-
-static void stopAutoscroll()
-{
-    isAutoScrolling = false;
-    autoscrollStartTime = 0L; //reset for next time
-}
-
-// This method computes the position of all the cards by updating bias based on a
-// simple interpolation model.  If the cards are still in motion, returns true.
-static bool doAutoscroll(float currentTime)
-{
-    if (autoscrollDuration == 0L) {
-        return false;
-    }
-
-    if (autoscrollStartTime == 0L) {
-        autoscrollStartTime = currentTime;
-    }
-
-    const int64_t interpolationEndTime = autoscrollStartTime + autoscrollDuration;
-
-    float timePos = (currentTime - autoscrollStartTime) / (float)autoscrollDuration;
-    if (timePos > 1.0f) {
-        timePos = 1.0f;
-    }
-
-    float lambda = timePos; //default to linear
-    if (autoscrollInterpolationMode == INTERPOLATION_DECELERATE_QUADRATIC) {
-        lambda = 1.0f - (1.0f - timePos) * (1.0f - timePos);
-    }
-    else if (autoscrollInterpolationMode == INTERPOLATION_ACCELERATE_DECELERATE_CUBIC) {
-        lambda = timePos * timePos * (3 - 2 * timePos);
-    }
-
-    bias = lambda * autoscrollStopAngle + (1.0 - lambda) * autoscrollStartAngle;
-
-    if (currentTime > interpolationEndTime) {
-        stopAutoscroll();
-        return false;
-    }
-    else {
-        return true;
-    }
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Hit detection using ray casting.
-////////////////////////////////////////////////////////////////////////////////////////////////////
-static const float EPSILON = 1.0e-6f;
-static const float tmin = 0.0f;
-
-static bool
-rayTriangleIntersect(Ray* ray, float3 p0, float3 p1, float3 p2, float* tout)
-{
-    float3 e1 = p1 - p0;
-    float3 e2 = p2 - p0;
-    float3 s1 = cross(ray->direction, e2);
-
-    float div = dot(s1, e1);
-    if (div == 0.0f) return false;  // ray is parallel to plane.
-
-    float3 d = ray->position - p0;
-    float invDiv = 1.0f / div;
-
-    float u = dot(d, s1) * invDiv;
-    if (u < 0.0f || u > 1.0f) return false;
-
-    float3 s2 = cross(d, e1);
-    float v = dot(ray->direction, s2) * invDiv;
-    if ( v < 0.0f || (u+v) > 1.0f) return false;
-
-    float t = dot(e2, s2) * invDiv;
-    if (t < tmin || t > *tout)
-        return false;
-    *tout = t;
-    return true;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Computes ray/plane intersection. Returns false if no intersection found.
-////////////////////////////////////////////////////////////////////////////////////////////////////
-static bool
-rayPlaneIntersect(Ray* ray, Plane* plane, float* tout)
-{
-    float denom = dot(ray->direction, plane->normal);
-    if (fabs(denom) > EPSILON) {
-        float t = - (plane->constant + dot(ray->position, plane->normal)) / denom;
-        if (t > tmin && t < *tout) {
-            *tout = t;
-            return true;
-        }
-    }
-    return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Computes ray/cylindr intersection. There are 0, 1 or 2 hits.
-// Returns true and sets *tout to the closest point or
-// returns false if no intersection found.
-////////////////////////////////////////////////////////////////////////////////////////////////////
-static bool
-rayCylinderIntersect(Ray* ray, Cylinder* cylinder, float* tout)
-{
-    const float A = ray->direction.x * ray->direction.x + ray->direction.z * ray->direction.z;
-    if (A < EPSILON) return false; // ray misses
-
-    // Compute quadratic equation coefficients
-    const float B = 2.0f * (ray->direction.x * ray->position.x
-            + ray->direction.z * ray->position.z);
-    const float C = ray->position.x * ray->position.x
-            + ray->position.z * ray->position.z
-            - cylinder->radius * cylinder->radius;
-    float disc = B*B - 4*A*C;
-
-    if (disc < 0.0f) return false; // ray misses
-    disc = sqrt(disc);
-    const float denom = 2.0f * A;
-
-    // Nearest point
-    const float t1 = (-B - disc) / denom;
-    if (dragModel == DRAG_MODEL_CYLINDER_OUTSIDE && t1 > tmin && t1 < *tout) {
-        *tout = t1;
-        return true;
-    }
-
-    // Far point
-    const float t2 = (-B + disc) / denom;
-    if (dragModel == DRAG_MODEL_CYLINDER_INSIDE && t2 > tmin && t2 < *tout) {
-        *tout = t2;
-        return true;
-    }
-    return false;
-}
-
-// Creates a ray for an Android pixel coordinate given a camera, ray and coordinates.
-// Note that the Y coordinate is opposite of GL rendering coordinates.
-static bool __attribute__((overloadable))
-makeRayForPixelAt(Ray* ray, PerspectiveCamera* cam, float x, float y)
-{
-    if (debugCamera) {
-        rsDebug("------ makeRay() -------", 0);
-        rsDebug("Camera.from:", cam->from);
-        rsDebug("Camera.at:", cam->at);
-        rsDebug("Camera.dir:", normalize(cam->at - cam->from));
-    }
-
-    // Vector math.  This has the potential to be much faster.
-    // TODO: pre-compute lowerLeftRay, du, dv to eliminate most of this math.
-    const float u = x / rsgGetWidth();
-    const float v = 1.0f - (y / rsgGetHeight());
-    const float aspect = (float) rsgGetWidth() / rsgGetHeight();
-    const float tanfov2 = 2.0f * tan(radians(cam->fov / 2.0f));
-    float3 dir = normalize(cam->at - cam->from);
-    float3 du = tanfov2 * normalize(cross(dir, cam->up));
-    float3 dv = tanfov2 * normalize(cross(du, dir));
-    du *= aspect;
-    float3 lowerLeftRay = dir - (0.5f * du) - (0.5f * dv);
-    const float3 rayPoint = cam->from;
-    const float3 rayDir = normalize(lowerLeftRay + u*du + v*dv);
-    if (debugCamera) {
-        rsDebug("Ray direction (vector math) = ", rayDir);
-    }
-
-    ray->position =  rayPoint;
-    ray->direction = rayDir;
-    return true;
-}
-
-// Creates a ray for an Android pixel coordinate given a model view and projection matrix.
-// Note that the Y coordinate is opposite of GL rendering coordinates.
-static bool __attribute__((overloadable))
-makeRayForPixelAt(Ray* ray, rs_matrix4x4* model, rs_matrix4x4* proj, float x, float y)
-{
-    rs_matrix4x4 pm = *model;
-    rsMatrixLoadMultiply(&pm, proj, model);
-    if (!rsMatrixInverse(&pm)) {
-        rsDebug("ERROR: SINGULAR PM MATRIX", 0);
-        return false;
-    }
-    const float width = rsgGetWidth();
-    const float height = rsgGetHeight();
-    const float winx = 2.0f * x / width - 1.0f;
-    const float winy = 2.0f * y / height - 1.0f;
-
-    float4 eye = { 0.0f, 0.0f, 0.0f, 1.0f };
-    float4 at = { winx, winy, 1.0f, 1.0f };
-
-    eye = rsMatrixMultiply(&pm, eye);
-    eye *= 1.0f / eye.w;
-
-    at = rsMatrixMultiply(&pm, at);
-    at *= 1.0f / at.w;
-
-    const float3 rayPoint = { eye.x, eye.y, eye.z };
-    const float3 atPoint = { at.x, at.y, at.z };
-    const float3 rayDir = normalize(atPoint - rayPoint);
-    if (debugCamera) {
-        rsDebug("winx: ", winx);
-        rsDebug("winy: ", winy);
-        rsDebug("Ray position (transformed) = ", eye);
-        rsDebug("Ray direction (transformed) = ", rayDir);
-    }
-    ray->position =  rayPoint;
-    ray->direction = rayDir;
-    return true;
-}
-
-static int intersectDetailTexture(float x, float y, float2 *tapCoordinates)
-{
-    for (int id = 0; id < cardCount; id++) {
-        if (cards[id].detailVisible) {
-            const int x0 = cards[id].detailTexturePosition[0].x;
-            const int y0 = cards[id].detailTexturePosition[0].y;
-            const int x1 = cards[id].detailTexturePosition[1].x;
-            const int y1 = cards[id].detailTexturePosition[1].y;
-            if (x >= x0 && x <= x1 && y >= y0 && y <= y1) {
-                float2 point = { x - x0, y - y0 };
-                *tapCoordinates = point;
-                return id;
-            }
-        }
-    }
-    return -1;
-}
-
-static int intersectGeometry(Ray* ray, float *bestTime)
-{
-    int hit = -1;
-    for (int id = 0; id < cardCount; id++) {
-        if (cards[id].cardVisible) {
-            rs_matrix4x4 matrix;
-            float3 p[4];
-
-            // Transform card vertices to world space
-            rsMatrixLoadIdentity(&matrix);
-            getMatrixForCard(&matrix, id, true, true);
-            for (int vertex = 0; vertex < 4; vertex++) {
-                float4 tmp = rsMatrixMultiply(&matrix, cardVertices[vertex]);
-                if (tmp.w != 0.0f) {
-                    p[vertex].x = tmp.x;
-                    p[vertex].y = tmp.y;
-                    p[vertex].z = tmp.z;
-                    p[vertex] *= 1.0f / tmp.w;
-                } else {
-                    rsDebug("Bad w coord: ", tmp);
-                }
-            }
-
-            // Intersect card geometry
-            if (rayTriangleIntersect(ray, p[0], p[1], p[2], bestTime)
-                || rayTriangleIntersect(ray, p[2], p[3], p[0], bestTime)) {
-                hit = id;
-            }
-        }
-    }
-    return hit;
-}
-
-// This method computes the position of all the cards by updating bias based on a
-// simple physics model.  If the cards are still in motion, returns true.
-static bool doPhysics(float dt)
-{
-    const float minStepTime = 1.0f / 300.0f; // ~5 steps per frame
-    const int N = (dt > minStepTime) ? (1 + round(dt / minStepTime)) : 1;
-    dt /= N;
-    for (int i = 0; i < N; i++) {
-        // Force friction - always opposes motion
-        const float Ff = -frictionCoeff * velocity;
-
-        // Restoring force to match cards with slots
-        const float theta = startAngle + bias;
-        const float dtheta = 2.0f * M_PI / slotCount;
-        const float position = theta / dtheta;
-        const float fraction = position - floor(position); // fractional position between slots
-        float x;
-        if (fraction > 0.5f) {
-            x = - (1.0f - fraction);
-        } else {
-            x = fraction;
-        }
-        const float Fr = - springConstant * x;
-
-        // compute velocity
-        const float momentum = mass * velocity + (Ff + Fr)*dt;
-        velocity = momentum / mass;
-        bias += velocity * dt;
-    }
-    return fabs(velocity) > stopVelocity;
-}
-
-static float easeOut(float x)
-{
-    return x;
-}
-
-// Computes the next value for bias using the current animation (physics/overscroll/autoscrolling)
-static bool updateNextPosition(int64_t currentTime)
-{
-    static const float biasMin = 1e-4f; // close enough if we're within this margin of result
-
-    float dt = deltaTimeInSeconds(currentTime);
-
-    if (dt <= 0.0f) {
-        if (debugRendering) rsDebug("Time delta was <= 0", dt);
-        return true;
-    }
-
-    const float firstBias = maximumBias();
-    const float lastBias = minimumBias();
-    bool stillAnimating = false;
-    if (isOverScrolling) {
-        if (tiltAngle > TILT_MIN_ANGLE) {
-            tiltAngle -= dt * TILT_MAX_ANGLE;
-            stillAnimating = true;
-        } else if (tiltAngle < -TILT_MIN_ANGLE) {
-            tiltAngle += dt * TILT_MAX_ANGLE;
-            stillAnimating = true;
-        } else {
-           isOverScrolling = false;
-           tiltAngle = false;
-           velocity = 0.0f;
-        }
-    } else if (isAutoScrolling) {
-        stillAnimating = doAutoscroll(currentTime);
-    } else {
-        stillAnimating = doPhysics(dt);
-        isOverScrolling = tiltAngle != 0;
-        if (isOverScrolling) {
-            velocity = 0.0f; // prevent bouncing due to v > 0 after overscroll animation.
-            stillAnimating = true;
-        }
-    }
-    bias = clamp(bias, lastBias, firstBias);
-    return stillAnimating;
-}
-
-// Cull cards based on visibility and visibleSlotCount.
-// If visibleSlotCount is > 0, then only show those slots and cull the rest.
-// Otherwise, it should cull based on bounds of geometry.
-static void cullCards()
-{
-    // Calculate the first and last angles of visible slots.  We include
-    // VISIBLE_SLOT_PADDING slots on either side of visibleSlotCount to allow
-    // cards to slide in / out at either side, and rely on the view frustrum
-    // for accurate clipping.
-    const float visibleFirst = slotPosition(-VISIBLE_SLOT_PADDING);
-    const float visibleLast = slotPosition(visibleSlotCount + VISIBLE_SLOT_PADDING);
-
-    // We'll load but not draw prefetchCardCountPerSide cards
-    // from either side of the visible slots.
-    const int prefetchCardCountPerSide = max(prefetchCardCount / 2, VISIBLE_SLOT_PADDING);
-    const float prefetchFirst = slotPosition(-prefetchCardCountPerSide);
-    const float prefetchLast = slotPosition(visibleSlotCount + prefetchCardCountPerSide);
-    for (int i = 0; i < cardCount; i++) {
-        if (visibleSlotCount > 0) {
-            // If visibleSlotCount is specified then only show cards between visibleFirst and visibleLast
-            float p = cardPosition(i);
-            if ((p >= prefetchFirst && p < prefetchLast)
-                    || (p <= prefetchFirst && p > prefetchLast)) {
-                cards[i].shouldPrefetch = true;
-                cards[i].cardVisible = (p >= visibleFirst && p < visibleLast)
-                        || (p <= visibleFirst && p > visibleLast);
-                // cards[i].detailVisible will be set at draw time
-            } else {
-                cards[i].shouldPrefetch = false;
-                cards[i].cardVisible = false;
-                cards[i].detailVisible = false;
-            }
-        } else {
-            // Cull the rest of the cards using bounding box of geometry.
-            // TODO
-            cards[i].cardVisible = true;
-            // cards[i].detailVisible will be set at draw time
-        }
-    }
-}
-
-// Request missing texture/geometry for a single card
-static void requestCardResources(int i) {
-    if (debugTextureLoading) rsDebug("*** Texture stamp: ", (int)cards[i].textureTimeStamp);
-    int data[1] = { i };
-
-    // request texture from client if not loaded
-    if (cards[i].textureState == STATE_INVALID) {
-        if (debugTextureLoading) rsDebug("Requesting card because state is STATE_INVALID", i);
-        bool enqueued = rsSendToClient(CMD_REQUEST_TEXTURE, data, sizeof(data));
-        if (enqueued) {
-            cards[i].textureState = STATE_LOADING;
-        } else {
-            if (debugTextureLoading) rsDebug("Couldn't send CMD_REQUEST_TEXTURE", i);
-        }
-    } else if (cards[i].textureState == STATE_STALE) {
-        if (debugTextureLoading) rsDebug("Requesting card because state is STATE_STALE", i);
-        bool enqueued = rsSendToClient(CMD_REQUEST_TEXTURE, data, sizeof(data));
-        if (enqueued) {
-            cards[i].textureState = STATE_UPDATING;
-        } else {
-            if (debugTextureLoading) rsDebug("Couldn't send CMD_REQUEST_TEXTURE", i);
-        }
-    }
-
-    // request detail texture from client if not loaded
-    if (cards[i].detailTextureState == STATE_INVALID) {
-        bool enqueued = rsSendToClient(CMD_REQUEST_DETAIL_TEXTURE, data, sizeof(data));
-        if (enqueued) {
-            cards[i].detailTextureState = STATE_LOADING;
-        } else {
-            if (debugTextureLoading) rsDebug("Couldn't send CMD_REQUEST_DETAIL_TEXTURE", i);
-        }
-    } else if (cards[i].detailTextureState == STATE_STALE) {
-        bool enqueued = rsSendToClient(CMD_REQUEST_DETAIL_TEXTURE, data, sizeof(data));
-        if (enqueued) {
-            cards[i].detailTextureState = STATE_UPDATING;
-        } else {
-            if (debugTextureLoading) rsDebug("Couldn't send CMD_REQUEST_DETAIL_TEXTURE", i);
-        }
-    }
-
-    // request geometry from client if not loaded
-    if (cards[i].geometryState == STATE_INVALID) {
-        bool enqueued = rsSendToClient(CMD_REQUEST_GEOMETRY, data, sizeof(data));
-        if (enqueued) {
-            cards[i].geometryState = STATE_LOADING;
-        } else {
-            if (debugGeometryLoading) rsDebug("Couldn't send CMD_REQUEST_GEOMETRY", i);
-        }
-    }
-}
-
-// Request texture/geometry for items that have come into view
-// or doesn't have a texture yet.
-static void updateCardResources(int64_t currentTime)
-{
-    // First process any visible cards
-    for (int i = cardCount-1; i >= 0; --i) {
-        if (cards[i].cardVisible) {
-            requestCardResources(i);
-        }
-    }
-
-    // Then the rest
-    for (int i = cardCount-1; i >= 0; --i) {
-        if (cards[i].cardVisible) {
-            // already requested above
-        } else if (cards[i].shouldPrefetch) {
-            requestCardResources(i);
-        } else {
-            // ask the host to remove the texture
-            int data[1];
-            if (cards[i].textureState != STATE_INVALID) {
-                data[0] = i;
-                bool enqueued = rsSendToClient(CMD_INVALIDATE_TEXTURE, data, sizeof(data));
-                if (enqueued) {
-                    cards[i].textureState = STATE_INVALID;
-                    cards[i].textureTimeStamp = currentTime;
-                } else {
-                    if (debugTextureLoading) rsDebug("Couldn't send CMD_INVALIDATE_TEXTURE", 0);
-                }
-            }
-            // ask the host to remove the detail texture
-            if (cards[i].detailTextureState != STATE_INVALID) {
-                data[0] = i;
-                bool enqueued = rsSendToClient(CMD_INVALIDATE_DETAIL_TEXTURE, data, sizeof(data));
-                if (enqueued) {
-                    cards[i].detailTextureState = STATE_INVALID;
-                    cards[i].detailTextureTimeStamp = currentTime;
-                } else {
-                    if (debugTextureLoading) rsDebug("Can't send CMD_INVALIDATE_DETAIL_TEXTURE", 0);
-                }
-            }
-            // ask the host to remove the geometry
-            if (cards[i].geometryState != STATE_INVALID) {
-                data[0] = i;
-                bool enqueued = rsSendToClient(CMD_INVALIDATE_GEOMETRY, data, sizeof(data));
-                if (enqueued) {
-                    cards[i].geometryState = STATE_INVALID;
-                } else {
-                    if (debugGeometryLoading) rsDebug("Couldn't send CMD_INVALIDATE_GEOMETRY", 0);
-                }
-            }
-        }
-    }
-}
-
-// Places dots on geometry to visually inspect that objects can be seen by rays.
-// NOTE: the color of the dot is somewhat random, as it depends on texture of previously-rendered
-// card.
-static void renderWithRays()
-{
-    const float w = rsgGetWidth();
-    const float h = rsgGetHeight();
-    const int skip = 8;
-
-    rsgProgramFragmentConstantColor(singleTextureFragmentProgram, 1.0f, 0.0f, 0.0f, 1.0f);
-    for (int j = 0; j < (int) h; j+=skip) {
-        float posY = (float) j;
-        for (int i = 0; i < (int) w; i+=skip) {
-            float posX = (float) i;
-            Ray ray;
-            if (makeRayForPixelAt(&ray, &camera, posX, posY)) {
-                float bestTime = FLT_MAX;
-                if (intersectGeometry(&ray, &bestTime) != -1) {
-                    rsgDrawSpriteScreenspace(posX, h - posY - 1, 0.0f, 2.0f, 2.0f);
-                }
-            }
-        }
-    }
-}
-
-int root() {
-    int64_t currentTime = rsUptimeMillis();
-
-    rsgBindProgramVertex(vertexProgram);
-    rsgBindProgramRaster(rasterProgram);
-    rsgBindSampler(singleTextureFragmentProgram, 0, linearClamp);
-    rsgBindSampler(multiTextureFragmentProgram, 0, linearClamp);
-    rsgBindSampler(multiTextureFragmentProgram, 1, linearClamp);
-
-    updateAllocationVars();
-
-    rsgBindProgramFragment(singleTextureFragmentProgram);
-    // rsgClearDepth() currently follows the value of glDepthMask(), so it's disabled when
-    // the mask is disabled. We may want to change the following to always draw w/o Z for
-    // the background if we can guarantee the depth buffer will get cleared and
-    // there's a performance advantage.
-    rsgBindProgramStore(programStoreBackground);
-    drawBackground();
-
-    updateCameraMatrix(rsgGetWidth(), rsgGetHeight());
-
-    bool stillAnimating = (currentTime - touchTime) <= ANIMATION_SCALE_UP_TIME;
-
-    if (!isDragging && animating) {
-        stillAnimating = updateNextPosition(currentTime);
-    }
-
-    lastTime = currentTime;
-
-    cullCards();
-
-    updateCardResources(currentTime);
-
-    // Draw cards opaque only if requested, and always draw detail textures with blending.
-    stillAnimating |= drawCards(currentTime);
-    rsgBindProgramStore(programStoreDetail);
-    stillAnimating |= drawDetails(currentTime);
-
-    if (stillAnimating != animating) {
-        if (stillAnimating) {
-            // we just started animating
-            sendAnimationStarted();
-        } else {
-            // we were animating but stopped animating just now
-            sendAnimationFinished();
-        }
-        animating = stillAnimating;
-    }
-
-    if (debugRays) {
-        renderWithRays();
-    }
-
-    //rsSendToClient(CMD_PING);
-
-    return animating ? 1 : 0;
-}
diff --git a/carousel/test/Android.mk b/carousel/test/Android.mk
deleted file mode 100644
index e00c83c..0000000
--- a/carousel/test/Android.mk
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# Copyright (C) 2009 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files) \
-    $(call all-renderscript-files-under, src) \
-    ../../../../frameworks/ex/carousel/java/com/android/ex/carousel/carousel.rs
-
-LOCAL_STATIC_JAVA_LIBRARIES := android-common-carousel
-
-LOCAL_PACKAGE_NAME := CarouselWidgetTests
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/carousel/test/AndroidManifest.xml b/carousel/test/AndroidManifest.xml
deleted file mode 100644
index 78b819d..0000000
--- a/carousel/test/AndroidManifest.xml
+++ /dev/null
@@ -1,69 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Copyright (C) 2009 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.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.carouseltest">
-
-    <uses-permission android:name="android.permission.GET_TASKS" />
-    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-
-    <application>
-
-        <activity
-            android:name="MusicDemoActivity"
-            android:label="@string/music_demo_activity_label"
-            android:theme="@android:style/Theme.NoTitleBar"
-            android:configChanges="orientation">
-
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.LAUNCHER" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-
-        </activity>
-
-        <activity
-            android:name="CarouselTestActivity"
-            android:label="@string/carousel_test_activity_label"
-            android:theme="@android:style/Theme.NoTitleBar"
-            android:configChanges="orientation">
-
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.LAUNCHER" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-
-        </activity>
-
-        <activity
-            android:name="TaskSwitcherActivity"
-            android:label="@string/task_switcher_activity_label"
-            android:theme="@android:style/Theme.NoTitleBar"
-            android:configChanges="orientation">
-
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.LAUNCHER" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-
-        </activity>
-
-    </application>
-</manifest>
diff --git a/carousel/test/res/anim/zoom_enter.xml b/carousel/test/res/anim/zoom_enter.xml
deleted file mode 100644
index f037208..0000000
--- a/carousel/test/res/anim/zoom_enter.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2009, 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.
-*/
--->
-
-<!-- Special window zoom animation: this is the element that enters the screen,
-     it starts at 200% and scales down.  Goes with zoom_exit.xml. -->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:interpolator="@android:anim/decelerate_interpolator">
-    <scale android:fromXScale="0.0" android:toXScale="1.0"
-           android:fromYScale="0.0" android:toYScale="1.0"
-           android:pivotX="50%p" android:pivotY="50%p"
-           android:duration="500" />
-    <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
-            android:duration="500"/>
-</set>
diff --git a/carousel/test/res/anim/zoom_exit.xml b/carousel/test/res/anim/zoom_exit.xml
deleted file mode 100644
index 207f570..0000000
--- a/carousel/test/res/anim/zoom_exit.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2009, 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.
-*/
--->
-
-<!-- Special window zoom animation: this is the element that exits the
-     screen, it is forced above the entering element and starts at its
-     normal size (filling the screen) and scales down while fading out.
-     This goes with zoom_enter.xml. -->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:interpolator="@android:anim/decelerate_interpolator"
-        android:zAdjustment="top">
-    <scale android:fromXScale="1.0" android:toXScale="4.0"
-           android:fromYScale="1.0" android:toYScale="4.0"
-           android:pivotX="50%p" android:pivotY="50%p"
-           android:duration="500" />
-    <alpha android:fromAlpha="1.0" android:toAlpha="0"
-            android:duration="500"/>
-</set>
diff --git a/carousel/test/res/drawable/background.png b/carousel/test/res/drawable/background.png
deleted file mode 100644
index 511f620..0000000
--- a/carousel/test/res/drawable/background.png
+++ /dev/null
Binary files differ
diff --git a/carousel/test/res/drawable/blank_album.png b/carousel/test/res/drawable/blank_album.png
deleted file mode 100644
index 76331d5..0000000
--- a/carousel/test/res/drawable/blank_album.png
+++ /dev/null
Binary files differ
diff --git a/carousel/test/res/drawable/border.png b/carousel/test/res/drawable/border.png
deleted file mode 100644
index 723b5a0..0000000
--- a/carousel/test/res/drawable/border.png
+++ /dev/null
Binary files differ
diff --git a/carousel/test/res/drawable/emo_im_angel.png b/carousel/test/res/drawable/emo_im_angel.png
deleted file mode 100644
index 10742a6..0000000
--- a/carousel/test/res/drawable/emo_im_angel.png
+++ /dev/null
Binary files differ
diff --git a/carousel/test/res/drawable/emo_im_cool.png b/carousel/test/res/drawable/emo_im_cool.png
deleted file mode 100644
index e3c8654..0000000
--- a/carousel/test/res/drawable/emo_im_cool.png
+++ /dev/null
Binary files differ
diff --git a/carousel/test/res/drawable/emo_im_crying.png b/carousel/test/res/drawable/emo_im_crying.png
deleted file mode 100644
index b23791c..0000000
--- a/carousel/test/res/drawable/emo_im_crying.png
+++ /dev/null
Binary files differ
diff --git a/carousel/test/res/drawable/emo_im_foot_in_mouth.png b/carousel/test/res/drawable/emo_im_foot_in_mouth.png
deleted file mode 100644
index 050b7be..0000000
--- a/carousel/test/res/drawable/emo_im_foot_in_mouth.png
+++ /dev/null
Binary files differ
diff --git a/carousel/test/res/drawable/emo_im_happy.png b/carousel/test/res/drawable/emo_im_happy.png
deleted file mode 100644
index 69e3bed..0000000
--- a/carousel/test/res/drawable/emo_im_happy.png
+++ /dev/null
Binary files differ
diff --git a/carousel/test/res/drawable/emo_im_kissing.png b/carousel/test/res/drawable/emo_im_kissing.png
deleted file mode 100644
index 0cca68e..0000000
--- a/carousel/test/res/drawable/emo_im_kissing.png
+++ /dev/null
Binary files differ
diff --git a/carousel/test/res/drawable/emo_im_laughing.png b/carousel/test/res/drawable/emo_im_laughing.png
deleted file mode 100644
index 8406ad0..0000000
--- a/carousel/test/res/drawable/emo_im_laughing.png
+++ /dev/null
Binary files differ
diff --git a/carousel/test/res/drawable/emo_im_lips_are_sealed.png b/carousel/test/res/drawable/emo_im_lips_are_sealed.png
deleted file mode 100644
index 222f175..0000000
--- a/carousel/test/res/drawable/emo_im_lips_are_sealed.png
+++ /dev/null
Binary files differ
diff --git a/carousel/test/res/drawable/emo_im_money_mouth.png b/carousel/test/res/drawable/emo_im_money_mouth.png
deleted file mode 100644
index d711bfb..0000000
--- a/carousel/test/res/drawable/emo_im_money_mouth.png
+++ /dev/null
Binary files differ
diff --git a/carousel/test/res/drawable/emo_im_sad.png b/carousel/test/res/drawable/emo_im_sad.png
deleted file mode 100644
index 40017f1..0000000
--- a/carousel/test/res/drawable/emo_im_sad.png
+++ /dev/null
Binary files differ
diff --git a/carousel/test/res/drawable/emo_im_surprised.png b/carousel/test/res/drawable/emo_im_surprised.png
deleted file mode 100644
index 4b2af7a..0000000
--- a/carousel/test/res/drawable/emo_im_surprised.png
+++ /dev/null
Binary files differ
diff --git a/carousel/test/res/drawable/emo_im_tongue_sticking_out.png b/carousel/test/res/drawable/emo_im_tongue_sticking_out.png
deleted file mode 100644
index 42ac80d..0000000
--- a/carousel/test/res/drawable/emo_im_tongue_sticking_out.png
+++ /dev/null
Binary files differ
diff --git a/carousel/test/res/drawable/emo_im_undecided.png b/carousel/test/res/drawable/emo_im_undecided.png
deleted file mode 100644
index 2cf5bd2..0000000
--- a/carousel/test/res/drawable/emo_im_undecided.png
+++ /dev/null
Binary files differ
diff --git a/carousel/test/res/drawable/emo_im_winking.png b/carousel/test/res/drawable/emo_im_winking.png
deleted file mode 100644
index a3a0876..0000000
--- a/carousel/test/res/drawable/emo_im_winking.png
+++ /dev/null
Binary files differ
diff --git a/carousel/test/res/drawable/emo_im_wtf.png b/carousel/test/res/drawable/emo_im_wtf.png
deleted file mode 100644
index 86c4bda..0000000
--- a/carousel/test/res/drawable/emo_im_wtf.png
+++ /dev/null
Binary files differ
diff --git a/carousel/test/res/drawable/emo_im_yelling.png b/carousel/test/res/drawable/emo_im_yelling.png
deleted file mode 100644
index cfd991a..0000000
--- a/carousel/test/res/drawable/emo_im_yelling.png
+++ /dev/null
Binary files differ
diff --git a/carousel/test/res/drawable/glossy_overlay.png b/carousel/test/res/drawable/glossy_overlay.png
deleted file mode 100644
index 4dfa3d9..0000000
--- a/carousel/test/res/drawable/glossy_overlay.png
+++ /dev/null
Binary files differ
diff --git a/carousel/test/res/drawable/specularmap.png b/carousel/test/res/drawable/specularmap.png
deleted file mode 100644
index 6b1c0d9..0000000
--- a/carousel/test/res/drawable/specularmap.png
+++ /dev/null
Binary files differ
diff --git a/carousel/test/res/drawable/unknown.png b/carousel/test/res/drawable/unknown.png
deleted file mode 100644
index 74bead5..0000000
--- a/carousel/test/res/drawable/unknown.png
+++ /dev/null
Binary files differ
diff --git a/carousel/test/res/drawable/wait.png b/carousel/test/res/drawable/wait.png
deleted file mode 100644
index e3f892f..0000000
--- a/carousel/test/res/drawable/wait.png
+++ /dev/null
Binary files differ
diff --git a/carousel/test/res/layout/carousel_test.xml b/carousel/test/res/layout/carousel_test.xml
deleted file mode 100644
index 86aa2e2..0000000
--- a/carousel/test/res/layout/carousel_test.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2008, 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.
-*/
--->
-
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical">
-
-    <View
-        android:layout_width="match_parent"
-        android:layout_height="100dip"
-        android:background="#ff800000"
-        android:visibility="gone"/>
-
-    <com.android.carouseltest.MyCarouselView
-        android:id="@+id/carousel"
-        android:layout_width="match_parent"
-        android:layout_height="0dip"
-        android:layout_weight="1"
-        android:layout_gravity="center">
-    </com.android.carouseltest.MyCarouselView>
-
-    <View
-        android:layout_width="match_parent"
-        android:layout_height="100dip"
-        android:background="#ff008000"
-        android:visibility="gone"/>
-
-</LinearLayout>
diff --git a/carousel/test/res/layout/music_demo.xml b/carousel/test/res/layout/music_demo.xml
deleted file mode 100644
index ba3e628..0000000
--- a/carousel/test/res/layout/music_demo.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2008, 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.
-*/
--->
-
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical">
-
-    <com.android.carouseltest.MyCarouselView
-        android:id="@+id/carousel"
-        android:layout_width="match_parent"
-        android:layout_height="0dip"
-        android:layout_weight="1">
-    </com.android.carouseltest.MyCarouselView>>
-
-</LinearLayout>
diff --git a/carousel/test/res/layout/taskswitcher.xml b/carousel/test/res/layout/taskswitcher.xml
deleted file mode 100644
index 2d07d54..0000000
--- a/carousel/test/res/layout/taskswitcher.xml
+++ /dev/null
@@ -1,55 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2008, 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.
-*/
--->
-
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical">
-
-    <!-- Title -->
-    <TextView
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:gravity="center"
-        android:textAppearance="?android:attr/textAppearanceSmall"
-        android:textColor="#80FFFFFF"
-        android:textStyle="bold"
-        android:singleLine="true"
-        android:text="@string/recent_tasks_title"
-        android:visibility="gone"/>
-
-    <!-- This is only intended to be visible when carousel is invisible -->
-    <TextView
-        android:id="@+id/no_applications_message"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center"
-        android:textAppearance="?android:attr/textAppearanceSmall"
-        android:text="@string/no_recent_tasks"
-        android:visibility="gone"/>
-
-    <com.android.carouseltest.MyCarouselView
-        android:id="@+id/carousel"
-        android:layout_width="match_parent"
-        android:layout_height="0dip"
-        android:layout_weight="1">
-    </com.android.carouseltest.MyCarouselView>>
-
-</LinearLayout>
diff --git a/carousel/test/res/raw/book.a3d b/carousel/test/res/raw/book.a3d
deleted file mode 100644
index 8dcfa61..0000000
--- a/carousel/test/res/raw/book.a3d
+++ /dev/null
Binary files differ
diff --git a/carousel/test/res/values-af/strings.xml b/carousel/test/res/values-af/strings.xml
deleted file mode 100644
index 88a3538..0000000
--- a/carousel/test/res/values-af/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"\'n Program wat wys hoe om Carousel te gebruik"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Onlangse programme"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Geen onlangse take nie"</string>
-</resources>
diff --git a/carousel/test/res/values-am/strings.xml b/carousel/test/res/values-am/strings.xml
deleted file mode 100644
index f1e8da2..0000000
--- a/carousel/test/res/values-am/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"የሙዚቃ Carousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"የCarousel ፍተሻ"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"የCarouselን ጥቅም የሚያሳይ መተግበሪያ"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"ክንውን ቀያያሪ"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"የቅርብ ጊዜ ትግበራዎች"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"ምንም የቅርብ ጊዜ ክንውን የለም"</string>
-</resources>
diff --git a/carousel/test/res/values-ar/strings.xml b/carousel/test/res/values-ar/strings.xml
deleted file mode 100644
index ba2a7be..0000000
--- a/carousel/test/res/values-ar/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"مكتبة الموسيقى"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"اختبار المكتبة"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"تطبيق لعرض استخدام المكتبة"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"مبدّل المهام"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"التطبيقات الأخيرة"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"لا توجد مهام حديثة"</string>
-</resources>
diff --git a/carousel/test/res/values-az-rAZ/strings.xml b/carousel/test/res/values-az-rAZ/strings.xml
deleted file mode 100644
index 634f926..0000000
--- a/carousel/test/res/values-az-rAZ/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Carousel istifadəsini göstərmək üçün tətbiq"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Son Tətbiqlər"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Son tapşırıqlar yoxdur"</string>
-</resources>
diff --git a/carousel/test/res/values-bg/strings.xml b/carousel/test/res/values-bg/strings.xml
deleted file mode 100644
index 41cf776..0000000
--- a/carousel/test/res/values-bg/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Приложение, което показва използването на въртележката"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Скорошни приложения"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Няма скорошни задачи"</string>
-</resources>
diff --git a/carousel/test/res/values-bn-rBD/strings.xml b/carousel/test/res/values-bn-rBD/strings.xml
deleted file mode 100644
index 1f63829..0000000
--- a/carousel/test/res/values-bn-rBD/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"সঙ্গীত ক্যারোসেল"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"ক্যারোসেল পরীক্ষা"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"ক্যারোসেলের ব্যবহার দেখানোর জন্য একটি অ্যাপ্লিকেশান"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"কার্য পরিবর্তনকারী"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"সাম্প্রতিক অ্যাপ্লিকেশানগুলি"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"কোনো সাম্প্রতিক কার্য নেই"</string>
-</resources>
diff --git a/carousel/test/res/values-ca/strings.xml b/carousel/test/res/values-ca/strings.xml
deleted file mode 100644
index 9f85f5e..0000000
--- a/carousel/test/res/values-ca/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Una aplicació per mostrar com es fa servir l\'expositor giratori"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Aplicacions usades recentment"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"No hi ha tasques recents"</string>
-</resources>
diff --git a/carousel/test/res/values-cs/strings.xml b/carousel/test/res/values-cs/strings.xml
deleted file mode 100644
index a9be826..0000000
--- a/carousel/test/res/values-cs/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Aplikace na ukázku použití režimu Carousel"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Nedávné aplikace"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Žádné nedávné úkoly"</string>
-</resources>
diff --git a/carousel/test/res/values-da/strings.xml b/carousel/test/res/values-da/strings.xml
deleted file mode 100644
index 4e7bf9d..0000000
--- a/carousel/test/res/values-da/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"Musikkarrusel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"Karruseltest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"En applikation, som viser  brugen af karrusellen"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Seneste applikationer"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Ingen seneste opgaver"</string>
-</resources>
diff --git a/carousel/test/res/values-de/strings.xml b/carousel/test/res/values-de/strings.xml
deleted file mode 100644
index 3dd5491..0000000
--- a/carousel/test/res/values-de/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Eine App, um die Verwendung des Karussells zu demonstrieren"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"Aufgabenwechsel"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Kürzlich geöffnete Apps"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Keine neuen Aufgaben"</string>
-</resources>
diff --git a/carousel/test/res/values-el/strings.xml b/carousel/test/res/values-el/strings.xml
deleted file mode 100644
index 872c9f5..0000000
--- a/carousel/test/res/values-el/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Αίτηση για την εμφάνιση της χρήσης του Καρουζέλ"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Πρόσφατες Εφαρμογές"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Δεν υπάρχουν πρόσφατες εργασίες"</string>
-</resources>
diff --git a/carousel/test/res/values-en-rGB/strings.xml b/carousel/test/res/values-en-rGB/strings.xml
deleted file mode 100644
index 86ea2cb..0000000
--- a/carousel/test/res/values-en-rGB/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"Music Carousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"Carousel Test"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"An application to show the use of Carousel"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"Task Switcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Recent Applications"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"No recent tasks"</string>
-</resources>
diff --git a/carousel/test/res/values-en-rIN/strings.xml b/carousel/test/res/values-en-rIN/strings.xml
deleted file mode 100644
index 86ea2cb..0000000
--- a/carousel/test/res/values-en-rIN/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"Music Carousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"Carousel Test"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"An application to show the use of Carousel"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"Task Switcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Recent Applications"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"No recent tasks"</string>
-</resources>
diff --git a/carousel/test/res/values-es-rUS/strings.xml b/carousel/test/res/values-es-rUS/strings.xml
deleted file mode 100644
index 43f83fa..0000000
--- a/carousel/test/res/values-es-rUS/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Una aplicación para mostrar el uso de Carousel"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Aplicaciones recientes"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"No hay tareas recientes"</string>
-</resources>
diff --git a/carousel/test/res/values-es/strings.xml b/carousel/test/res/values-es/strings.xml
deleted file mode 100644
index 4e9e63f..0000000
--- a/carousel/test/res/values-es/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"Carrusel de música"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"Prueba de carrusel"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Una aplicación para mostrar cómo se usa el carrusel"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"Cambio de tarea"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Aplicaciones recientes"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"No hay tareas recientes."</string>
-</resources>
diff --git a/carousel/test/res/values-et-rEE/strings.xml b/carousel/test/res/values-et-rEE/strings.xml
deleted file mode 100644
index 59f0b5c..0000000
--- a/carousel/test/res/values-et-rEE/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Rakendus, mis näitab karusselli kasutust"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Hiljutised rakendused"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Hiljutised ülesanded puuduvad"</string>
-</resources>
diff --git a/carousel/test/res/values-eu-rES/strings.xml b/carousel/test/res/values-eu-rES/strings.xml
deleted file mode 100644
index 95fc697..0000000
--- a/carousel/test/res/values-eu-rES/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"Musikaren menu birakaria"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"Menu birakariaren proba"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Menu birakariaren erabilera erakusteko aplikazio bat"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"Zeregin-aldatzailea"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Azken aplikazioak"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Ez dago azkenaldiko zereginik"</string>
-</resources>
diff --git a/carousel/test/res/values-fa/strings.xml b/carousel/test/res/values-fa/strings.xml
deleted file mode 100644
index 88aae52..0000000
--- a/carousel/test/res/values-fa/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"گردونه موسیقی"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"برنامه‌ای برای نشان دادن استفاده از گردونه"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"برنامه‌های اخیر"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"کار جدیدی موجود نیست"</string>
-</resources>
diff --git a/carousel/test/res/values-fi/strings.xml b/carousel/test/res/values-fi/strings.xml
deleted file mode 100644
index e5434a6..0000000
--- a/carousel/test/res/values-fi/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Sovellus opastaa karusellin käytössä"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Viimeisimmät sovellukset"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Ei viimeisimpiä tehtäviä"</string>
-</resources>
diff --git a/carousel/test/res/values-fr-rCA/strings.xml b/carousel/test/res/values-fr-rCA/strings.xml
deleted file mode 100644
index 87aeb34..0000000
--- a/carousel/test/res/values-fr-rCA/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Une application expliquant l\'utilisation de Carousel"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Applications récentes"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Aucune tâche récente"</string>
-</resources>
diff --git a/carousel/test/res/values-fr/strings.xml b/carousel/test/res/values-fr/strings.xml
deleted file mode 100644
index 87aeb34..0000000
--- a/carousel/test/res/values-fr/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Une application expliquant l\'utilisation de Carousel"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Applications récentes"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Aucune tâche récente"</string>
-</resources>
diff --git a/carousel/test/res/values-gl-rES/strings.xml b/carousel/test/res/values-gl-rES/strings.xml
deleted file mode 100644
index 5d41718..0000000
--- a/carousel/test/res/values-gl-rES/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Unha aplicación para mostrar o uso do expositor xiratorio"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Aplicacións recentes"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Non hai tarefas recentes"</string>
-</resources>
diff --git a/carousel/test/res/values-hi/strings.xml b/carousel/test/res/values-hi/strings.xml
deleted file mode 100644
index b931761..0000000
--- a/carousel/test/res/values-hi/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Carousel का उपयोग बताने के लिए एप्‍लि‍केशन"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"हाल ही के एप्‍लि‍केशन"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"कोई हाल ही के कार्य नहीं"</string>
-</resources>
diff --git a/carousel/test/res/values-hr/strings.xml b/carousel/test/res/values-hr/strings.xml
deleted file mode 100644
index 8fe4b5f..0000000
--- a/carousel/test/res/values-hr/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Aplikacija koja pokazuje kako se upotrebljava Carousel"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Nedavne aplikacije"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Nema nedavnih zadataka"</string>
-</resources>
diff --git a/carousel/test/res/values-hu/strings.xml b/carousel/test/res/values-hu/strings.xml
deleted file mode 100644
index 102e4e9..0000000
--- a/carousel/test/res/values-hu/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"ZeneKörhinta"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"KörhintaTeszt"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"A Körhinta használatát megjelenítő alkalmazás"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"FeladatVáltó"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"A legújabb alkalmazások"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Nincsenek esedékes feladatok"</string>
-</resources>
diff --git a/carousel/test/res/values-hy-rAM/strings.xml b/carousel/test/res/values-hy-rAM/strings.xml
deleted file mode 100644
index 39bf205..0000000
--- a/carousel/test/res/values-hy-rAM/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Հավելված` Carousel-ի օգտագործումը ցույց տալու համար"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Վերջին հավելվածները"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Վերջին առաջադրանքներ չկան"</string>
-</resources>
diff --git a/carousel/test/res/values-in/strings.xml b/carousel/test/res/values-in/strings.xml
deleted file mode 100644
index 06c8812..0000000
--- a/carousel/test/res/values-in/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"KaruselMusik"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"UjiKarusel"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Aplikasi untuk menampilkan penggunaan Korsel"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"PengubahTugas"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Aplikasi Terbaru"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Tidak ada tugas terbaru"</string>
-</resources>
diff --git a/carousel/test/res/values-is-rIS/strings.xml b/carousel/test/res/values-is-rIS/strings.xml
deleted file mode 100644
index 8971edf..0000000
--- a/carousel/test/res/values-is-rIS/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"Tónlistarvalræma"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"Valræmuprófun"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Forrit til að sýna notkun valræmu"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"Verkefnaskiptir"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Nýleg forrit"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Engin nýleg verkefni"</string>
-</resources>
diff --git a/carousel/test/res/values-it/strings.xml b/carousel/test/res/values-it/strings.xml
deleted file mode 100644
index 86e5516..0000000
--- a/carousel/test/res/values-it/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Un\'applicazione per mostrare l\'uso della sequenza"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Applicazioni recenti"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Nessuna attività recente"</string>
-</resources>
diff --git a/carousel/test/res/values-iw/strings.xml b/carousel/test/res/values-iw/strings.xml
deleted file mode 100644
index a4163c5..0000000
--- a/carousel/test/res/values-iw/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"אפליקציה להצגת השימוש בקרוסלה"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"אפליקציות אחרונות"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"אין משימות אחרונות"</string>
-</resources>
diff --git a/carousel/test/res/values-ja/strings.xml b/carousel/test/res/values-ja/strings.xml
deleted file mode 100644
index 9b2cf5b..0000000
--- a/carousel/test/res/values-ja/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Carouselの使用を表示するアプリケーション"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"最近のアプリケーション"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"最近のタスクはありません"</string>
-</resources>
diff --git a/carousel/test/res/values-ka-rGE/strings.xml b/carousel/test/res/values-ka-rGE/strings.xml
deleted file mode 100644
index 0764f3f..0000000
--- a/carousel/test/res/values-ka-rGE/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Carousel-ის გამოყენების მაჩვენებელი აპლიკაცია"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"ბოლოდროინდელი აპლიკაციები"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"ბოლოდროინდელი ამოცანები არ არის."</string>
-</resources>
diff --git a/carousel/test/res/values-kk-rKZ/strings.xml b/carousel/test/res/values-kk-rKZ/strings.xml
deleted file mode 100644
index 8192813..0000000
--- a/carousel/test/res/values-kk-rKZ/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"МузыкаКарусель"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"КарусельТест"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Карусельді қолдану жолын көрсететін қолданба"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"ТапсырмаАуыстырғыш"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Соңғы қолданбалар"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Соңғы тапсырмалар жоқ"</string>
-</resources>
diff --git a/carousel/test/res/values-km-rKH/strings.xml b/carousel/test/res/values-km-rKH/strings.xml
deleted file mode 100644
index 5bb198d..0000000
--- a/carousel/test/res/values-km-rKH/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"កម្មវិធី​ត្រូវ​បង្ហាញ​ការ​ប្រើ Carousel"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"កម្មវិធី​ថ្មីៗ"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"គ្មាន​ភារកិច្ច​ថ្មីៗ"</string>
-</resources>
diff --git a/carousel/test/res/values-kn-rIN/strings.xml b/carousel/test/res/values-kn-rIN/strings.xml
deleted file mode 100644
index 6b62867..0000000
--- a/carousel/test/res/values-kn-rIN/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"ಕರೋಸೆಲ್ ಬಳಕೆಯನ್ನು ತೋರಿಸುವ ಅಪ್ಲಿಕೇಶನ್"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"ಇತ್ತೀಚಿನ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"ಇತ್ತೀಚಿನ ಕಾರ್ಯಗಳಿಲ್ಲ"</string>
-</resources>
diff --git a/carousel/test/res/values-ko/strings.xml b/carousel/test/res/values-ko/strings.xml
deleted file mode 100644
index eeb5b66..0000000
--- a/carousel/test/res/values-ko/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"음악 캐러셀"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"캐러셀 테스트"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"캐러셀 사용을 표시하는 애플리케이션"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"작업 전환"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"최신 애플리케이션"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"최근 작업이 없습니다."</string>
-</resources>
diff --git a/carousel/test/res/values-ky-rKG/strings.xml b/carousel/test/res/values-ky-rKG/strings.xml
deleted file mode 100644
index ddca10f..0000000
--- a/carousel/test/res/values-ky-rKG/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"МузыкалыкАйланкөчөк"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"АйланкөчөктүСыноо"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Колдонмо көргөзүүдө Айланкөчөк ыкмасын колдонот"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"ТапшырмаКоторгуч"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Акыркы колдонмолор"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Акыркы тапшырмалар табылган жок"</string>
-</resources>
diff --git a/carousel/test/res/values-lo-rLA/strings.xml b/carousel/test/res/values-lo-rLA/strings.xml
deleted file mode 100644
index 83a4cbd..0000000
--- a/carousel/test/res/values-lo-rLA/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"ແອັບພລິເຄຊັນທີ່ໃຊ້ສະແດງປະໂຫຍດຂອງ Carousel"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"ແອັບຯພລິເຄຊັນທີ່ຫາກໍໃຊ້"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"ບໍ່ມີວຽກເມື່ອໄວໆນີ້ເທື່ອ"</string>
-</resources>
diff --git a/carousel/test/res/values-lt/strings.xml b/carousel/test/res/values-lt/strings.xml
deleted file mode 100644
index 5fd9993..0000000
--- a/carousel/test/res/values-lt/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"Muzikos karuselė"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"Karuselės testas"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Programa, rodanti karuselės naudojimą"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"Užduočių jungiklis"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Naujausios programos"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Nė vienos pastaruoju metu pateiktos užduoties"</string>
-</resources>
diff --git a/carousel/test/res/values-lv/strings.xml b/carousel/test/res/values-lv/strings.xml
deleted file mode 100644
index ba5f6f1..0000000
--- a/carousel/test/res/values-lv/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Lietojumprogramma karuseļa lietošanas demonstrēšanai"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Nesen lietotās lietojumprogrammas"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Nav neviena nesen veikta uzdevuma."</string>
-</resources>
diff --git a/carousel/test/res/values-mk-rMK/strings.xml b/carousel/test/res/values-mk-rMK/strings.xml
deleted file mode 100644
index b7c1834..0000000
--- a/carousel/test/res/values-mk-rMK/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Апликација да се покаже употребата на Carousel"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Последни апликации"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Нема понови задачи"</string>
-</resources>
diff --git a/carousel/test/res/values-ml-rIN/strings.xml b/carousel/test/res/values-ml-rIN/strings.xml
deleted file mode 100644
index 73254d6..0000000
--- a/carousel/test/res/values-ml-rIN/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"കറൗസലിന്റെ ഉപയോഗം ദൃശ്യമാക്കാനുള്ള ഒരു അപ്ലിക്കേഷൻ"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"സമീപകാല അപ്‌ളിക്കേഷനുകൾ"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"സമീപകാല ടാസ്‌ക്കുകളൊന്നുമില്ല"</string>
-</resources>
diff --git a/carousel/test/res/values-mn-rMN/strings.xml b/carousel/test/res/values-mn-rMN/strings.xml
deleted file mode 100644
index 20d9f8d..0000000
--- a/carousel/test/res/values-mn-rMN/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"Хөгжмийн тойруулга"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"Тойруулга тест"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Тойруулга ашиглалтыг харуулах аппликешн"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"Даалгавар солигч"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Сүүлийн аппликешн"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Сүүлийн даалгавар хоосон"</string>
-</resources>
diff --git a/carousel/test/res/values-mr-rIN/strings.xml b/carousel/test/res/values-mr-rIN/strings.xml
deleted file mode 100644
index aa0b2e6..0000000
--- a/carousel/test/res/values-mr-rIN/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"कॅरोझेलचा वापर दर्शविण्‍यासाठी अनुप्रयोग"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"अलीकडील अनुप्रयोग"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"अलीकडील कोणतीही कार्ये नाहीत"</string>
-</resources>
diff --git a/carousel/test/res/values-ms-rMY/strings.xml b/carousel/test/res/values-ms-rMY/strings.xml
deleted file mode 100644
index ab9381a..0000000
--- a/carousel/test/res/values-ms-rMY/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Satu aplikasi untuk menunjukkan penggunaan Carousel"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Aplikasi Terbaru"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Tiada tugasan terbaru"</string>
-</resources>
diff --git a/carousel/test/res/values-my-rMM/strings.xml b/carousel/test/res/values-my-rMM/strings.xml
deleted file mode 100644
index 11bf0d8..0000000
--- a/carousel/test/res/values-my-rMM/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"Carouselဂီတ"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"Carouselစမ်းသပ်ခြင်း"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Carouselအားအသုံးပြုရန်ပြသော အပ်ပလီကေးရှင်း"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"လုပ်ငန်းစဉ်ဖလှယ်မှု"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"လတ်တလောအသုံးပြုသော အပ်ပလီကေးရှင်းများ"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"လတ်တလောလုပ်ဆောင်ချက်မရှိပါ"</string>
-</resources>
diff --git a/carousel/test/res/values-nb/strings.xml b/carousel/test/res/values-nb/strings.xml
deleted file mode 100644
index 751baf9..0000000
--- a/carousel/test/res/values-nb/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"En app som viser bruken av Carousel"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Nylige apper"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Ingen nylige oppgaver"</string>
-</resources>
diff --git a/carousel/test/res/values-ne-rNP/strings.xml b/carousel/test/res/values-ne-rNP/strings.xml
deleted file mode 100644
index 838502f..0000000
--- a/carousel/test/res/values-ne-rNP/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"संगीत करउसेल"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"करउसेल परीक्षण"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"कारउसेलको प्रयोग देखाउन एउटा अनुप्रयोग"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"कार्य स्विच गर्ने"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"भर्खरैका अनुप्रयोगहरू"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"कुनै भरखरका कार्यहरू छैनन्।"</string>
-</resources>
diff --git a/carousel/test/res/values-nl/strings.xml b/carousel/test/res/values-nl/strings.xml
deleted file mode 100644
index 3ec92ed..0000000
--- a/carousel/test/res/values-nl/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Een app die het gebruik van Carousel illustreert"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Recente apps"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Geen recente taken"</string>
-</resources>
diff --git a/carousel/test/res/values-pl/strings.xml b/carousel/test/res/values-pl/strings.xml
deleted file mode 100644
index c811c04..0000000
--- a/carousel/test/res/values-pl/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Aplikacja prezentująca zastosowanie karuzeli"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Ostatnie aplikacje"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Brak ostatnich zadań"</string>
-</resources>
diff --git a/carousel/test/res/values-pt-rPT/strings.xml b/carousel/test/res/values-pt-rPT/strings.xml
deleted file mode 100644
index 11104d4..0000000
--- a/carousel/test/res/values-pt-rPT/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Uma aplicação para demonstrar a utilização do Carousel"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Aplicações Recentes"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Sem tarefas recentes"</string>
-</resources>
diff --git a/carousel/test/res/values-pt/strings.xml b/carousel/test/res/values-pt/strings.xml
deleted file mode 100644
index f98edde..0000000
--- a/carousel/test/res/values-pt/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Um aplicativo para mostrar o uso do Carousel"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Aplicativos recentes"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Nenhuma tarefa recente"</string>
-</resources>
diff --git a/carousel/test/res/values-ro/strings.xml b/carousel/test/res/values-ro/strings.xml
deleted file mode 100644
index 9c8df37..0000000
--- a/carousel/test/res/values-ro/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"O aplicaţie care afişează cum se utilizează Caruselul"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Aplicaţii recente"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Nicio activitate recentă"</string>
-</resources>
diff --git a/carousel/test/res/values-ru/strings.xml b/carousel/test/res/values-ru/strings.xml
deleted file mode 100644
index af64195..0000000
--- a/carousel/test/res/values-ru/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"Музыкальная карусель"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"Тестирование карусели"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Приложение для отображения карусели"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"Смена задач"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Последние приложения"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Нет новых задач"</string>
-</resources>
diff --git a/carousel/test/res/values-si-rLK/strings.xml b/carousel/test/res/values-si-rLK/strings.xml
deleted file mode 100644
index 5a1aa48..0000000
--- a/carousel/test/res/values-si-rLK/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"සංගීත Carousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"Carousel පරීක්ෂණය"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Carousel භාවිතය පෙන්වීමට යෙදුමකි"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"කාර්ය ස්විචය"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"මෑත කාලීන යෙදුම්"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"මෑත කාර්යයන් නැත"</string>
-</resources>
diff --git a/carousel/test/res/values-sk/strings.xml b/carousel/test/res/values-sk/strings.xml
deleted file mode 100644
index e6e8aa1..0000000
--- a/carousel/test/res/values-sk/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Aplikácia na ukážku použitia režimu Carousel"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Nedávne aplikácie"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Žiadne nedávne úlohy"</string>
-</resources>
diff --git a/carousel/test/res/values-sl/strings.xml b/carousel/test/res/values-sl/strings.xml
deleted file mode 100644
index ca10e66..0000000
--- a/carousel/test/res/values-sl/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"Glasbeni vrtiljak"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"Preskus vrtiljaka"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Program za prikaz uporabe pogleda vrtiljaka"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"Izbirnik opravil"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Nedavni programi"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Ni nedavnih opravil"</string>
-</resources>
diff --git a/carousel/test/res/values-sr/strings.xml b/carousel/test/res/values-sr/strings.xml
deleted file mode 100644
index 312fc41..0000000
--- a/carousel/test/res/values-sr/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Апликација којом се приказује коришћење Carousel-а"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Недавно коришћене апликације"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Нема недавних задатака"</string>
-</resources>
diff --git a/carousel/test/res/values-sv/strings.xml b/carousel/test/res/values-sv/strings.xml
deleted file mode 100644
index ca070e3..0000000
--- a/carousel/test/res/values-sv/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"Musikkarusell"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"Karuselltest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"En app om hur du använder Karusell"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Nya appar"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Inga nya aktiviteter"</string>
-</resources>
diff --git a/carousel/test/res/values-sw/strings.xml b/carousel/test/res/values-sw/strings.xml
deleted file mode 100644
index 350664f..0000000
--- a/carousel/test/res/values-sw/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"Jaribio la Carousel"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Programu ya kuonyesha matumizi ya Karuseli"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Programu za Hivi karibuni"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Hakuna kazi za hivi karibuni"</string>
-</resources>
diff --git a/carousel/test/res/values-ta-rIN/strings.xml b/carousel/test/res/values-ta-rIN/strings.xml
deleted file mode 100644
index 7ae9434..0000000
--- a/carousel/test/res/values-ta-rIN/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Carousel இன் பயன்பாட்டைக் காட்டுவதற்கான பயன்பாடு"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"சமீபத்திய பயன்பாடுகள்"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"செயல் ஏதுமில்லை"</string>
-</resources>
diff --git a/carousel/test/res/values-te-rIN/strings.xml b/carousel/test/res/values-te-rIN/strings.xml
deleted file mode 100644
index b7a6218..0000000
--- a/carousel/test/res/values-te-rIN/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"తిరిగే సంగీత పట్టిక"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"తిరిగే పట్టిక పరీక్ష"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"తిరిగే పట్టిక ఉపయోగాన్ని చూపే అనువర్తనం"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"విధి స్విచ్చర్"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"ఇటీవలి అనువర్తనాలు"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"ఇటీవలి విధులు లేవు"</string>
-</resources>
diff --git a/carousel/test/res/values-th/strings.xml b/carousel/test/res/values-th/strings.xml
deleted file mode 100644
index fa448a6..0000000
--- a/carousel/test/res/values-th/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"แอปพลิเคชันที่แสดงการใช้งาน Carousel"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"แอปพลิเคชันล่าสุด"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"ไม่มีงานล่าสุด"</string>
-</resources>
diff --git a/carousel/test/res/values-tl/strings.xml b/carousel/test/res/values-tl/strings.xml
deleted file mode 100644
index a074480..0000000
--- a/carousel/test/res/values-tl/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Isang application upang ipakita ang gamit ng Carousel"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Mga Kamakailang Application"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Walang kamakailang mga gawain"</string>
-</resources>
diff --git a/carousel/test/res/values-tr/strings.xml b/carousel/test/res/values-tr/strings.xml
deleted file mode 100644
index 38c217b..0000000
--- a/carousel/test/res/values-tr/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"Müzik Atlı Karıncası"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"Atlı Karınca Testi"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Atlı Karınca\'nın kullanımını göstermek için bir uygulama"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"Görev Değiştirici"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Son Uygulamalar"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Hiç son görev yok"</string>
-</resources>
diff --git a/carousel/test/res/values-uk/strings.xml b/carousel/test/res/values-uk/strings.xml
deleted file mode 100644
index 41fc7ac..0000000
--- a/carousel/test/res/values-uk/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Програма для демонстрації режиму каруселі"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Останні програми"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Немає останніх завдань"</string>
-</resources>
diff --git a/carousel/test/res/values-ur-rPK/strings.xml b/carousel/test/res/values-ur-rPK/strings.xml
deleted file mode 100644
index 2eb1e3d..0000000
--- a/carousel/test/res/values-ur-rPK/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"کیراسیل کا استعمال دکھانے کیلئے ایک ایپلیکیشن"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"حالیہ ایپلیکیشنز"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"کوئی حالیہ ٹاسکس نہیں ہیں"</string>
-</resources>
diff --git a/carousel/test/res/values-uz-rUZ/strings.xml b/carousel/test/res/values-uz-rUZ/strings.xml
deleted file mode 100644
index 9c8c83e..0000000
--- a/carousel/test/res/values-uz-rUZ/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"\"Carousel\"dan foydalanib ko‘rsatish uchun dastur"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"So‘nggi foydalanilgan dasturlar"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"So‘nggi vazifalar mavjud emas"</string>
-</resources>
diff --git a/carousel/test/res/values-vi/strings.xml b/carousel/test/res/values-vi/strings.xml
deleted file mode 100644
index 2ac1dbc..0000000
--- a/carousel/test/res/values-vi/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Ứng dụng thể hiện việc sử dụng Carousel"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Ứng dụng gần đây"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Không có tác vụ nào gần đây"</string>
-</resources>
diff --git a/carousel/test/res/values-zh-rCN/strings.xml b/carousel/test/res/values-zh-rCN/strings.xml
deleted file mode 100644
index 2273e8f..0000000
--- a/carousel/test/res/values-zh-rCN/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"音乐轮播"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"轮播测试"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"介绍轮播用法的应用"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"任务切换器"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"最近用过的应用"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"无任何近期任务"</string>
-</resources>
diff --git a/carousel/test/res/values-zh-rHK/strings.xml b/carousel/test/res/values-zh-rHK/strings.xml
deleted file mode 100644
index 193cb4a..0000000
--- a/carousel/test/res/values-zh-rHK/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"展示輪轉使用方法的應用程式"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"最近使用的應用程式"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"最近沒有任務"</string>
-</resources>
diff --git a/carousel/test/res/values-zh-rTW/strings.xml b/carousel/test/res/values-zh-rTW/strings.xml
deleted file mode 100644
index 85940cf..0000000
--- a/carousel/test/res/values-zh-rTW/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"示範輪轉介面使用方法的應用程式"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"最近用過的應用程式"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"沒有近期的工作"</string>
-</resources>
diff --git a/carousel/test/res/values-zu/strings.xml b/carousel/test/res/values-zu/strings.xml
deleted file mode 100644
index bd5be32..0000000
--- a/carousel/test/res/values-zu/strings.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/*
-* Copyright (C) 2009 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="music_demo_activity_label" msgid="4382090808250495841">"i-MusicCarousel"</string>
-    <string name="carousel_test_activity_label" msgid="6014624482213318747">"I-CarouselTest"</string>
-    <string name="carousel_test_activity_description" msgid="1632693812604375483">"Isisetshenziswa sokukhombisa ukusetshenziswa kwe-Carousel"</string>
-    <string name="task_switcher_activity_label" msgid="714620143340933546">"i-TaskSwitcher"</string>
-    <string name="recent_tasks_title" msgid="1030287226205477117">"Izisetshenziswa zamaduze nje"</string>
-    <string name="no_recent_tasks" msgid="6884096266670555780">"Ayikho imisebenzi yamanje"</string>
-</resources>
diff --git a/carousel/test/res/values/strings.xml b/carousel/test/res/values/strings.xml
deleted file mode 100644
index c0b5ce6..0000000
--- a/carousel/test/res/values/strings.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-* Copyright (C) 2009 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.
-*/
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- General --><skip />
-    <string name="music_demo_activity_label">MusicCarousel</string>
-    <string name="carousel_test_activity_label">CarouselTest</string>
-    <string name="carousel_test_activity_description">An application to show the use of Carousel</string>
-    <string name="task_switcher_activity_label">TaskSwitcher</string>
-
-    <string name="recent_tasks_title">Recent Applications</string>
-    <string name="no_recent_tasks">No recent tasks</string>
-
-</resources>
diff --git a/carousel/test/src/com/android/carouseltest/CarouselTestActivity.java b/carousel/test/src/com/android/carouseltest/CarouselTestActivity.java
deleted file mode 100644
index 18adc5e..0000000
--- a/carousel/test/src/com/android/carouseltest/CarouselTestActivity.java
+++ /dev/null
@@ -1,184 +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.carouseltest;
-
-import com.android.ex.carousel.CarouselView;
-import com.android.ex.carousel.CarouselViewHelper;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.PixelFormat;
-import android.graphics.Rect;
-import android.os.Bundle;
-import android.util.Log;
-
-public class CarouselTestActivity extends Activity {
-    private static final String TAG = "CarouselTestActivity";
-    private static final int CARD_SLOTS = 56;
-    private static final int TOTAL_CARDS = 100;
-    private static final int TEXTURE_HEIGHT = 256;
-    private static final int TEXTURE_WIDTH = 256;
-    private static final int SLOTS_VISIBLE = 7;
-
-    protected static final boolean DBG = false;
-    private static final int DETAIL_TEXTURE_WIDTH = 200;
-    private static final int DETAIL_TEXTURE_HEIGHT = 80;
-    private static final int VISIBLE_DETAIL_COUNT = 3;
-    private static boolean INCREMENTAL_ADD = false; // To debug incrementally adding cards
-    private CarouselView mView;
-    private Paint mPaint = new Paint();
-    private CarouselViewHelper mHelper;
-    private Bitmap mGlossyOverlay;
-    private Bitmap mBorder;
-
-    class LocalCarouselViewHelper extends CarouselViewHelper {
-        private static final int PIXEL_BORDER = 3;
-        private DetailTextureParameters mDetailTextureParameters
-                = new DetailTextureParameters(5.0f, 5.0f, 3.0f, 10.0f);
-
-        LocalCarouselViewHelper(Context context) {
-            super(context);
-        }
-
-        @Override
-        public void onCardSelected(final int id) {
-            postMessage("Selection", "Card " + id + " was selected");
-        }
-
-        @Override
-        public void onDetailSelected(final int id, int x, int y) {
-            postMessage("Selection", "Detail for card " + id + " was selected");
-        }
-
-        @Override
-        public void onCardLongPress(int n, int touchPosition[], Rect detailCoordinates) {
-            postMessage("Selection", "Long press on card " + n);
-        }
-
-        @Override
-        public DetailTextureParameters getDetailTextureParameters(int id) {
-            return mDetailTextureParameters;
-        }
-
-        @Override
-        public Bitmap getTexture(int n) {
-            Bitmap bitmap = Bitmap.createBitmap(TEXTURE_WIDTH, TEXTURE_HEIGHT,
-                    Bitmap.Config.ARGB_8888);
-            Canvas canvas = new Canvas(bitmap);
-            canvas.drawARGB(0, 0, 0, 0);
-            mPaint.setColor(0x40808080);
-            canvas.drawRect(2, 2, TEXTURE_WIDTH-2, TEXTURE_HEIGHT-2, mPaint);
-            mPaint.setTextSize(100.0f);
-            mPaint.setAntiAlias(true);
-            mPaint.setColor(0xffffffff);
-            canvas.drawText("" + n, 2, TEXTURE_HEIGHT-10, mPaint);
-            canvas.drawBitmap(mGlossyOverlay, null,
-                    new Rect(PIXEL_BORDER, PIXEL_BORDER,
-                            TEXTURE_WIDTH - PIXEL_BORDER, TEXTURE_HEIGHT - PIXEL_BORDER), mPaint);
-            return bitmap;
-        }
-
-        @Override
-        public Bitmap getDetailTexture(int n) {
-            Bitmap bitmap = Bitmap.createBitmap(DETAIL_TEXTURE_WIDTH, DETAIL_TEXTURE_HEIGHT,
-                    Bitmap.Config.ARGB_8888);
-            Canvas canvas = new Canvas(bitmap);
-            canvas.drawARGB(32, 10, 10, 10);
-            mPaint.setTextSize(15.0f);
-            mPaint.setAntiAlias(true);
-            canvas.drawText("Detail text for card " + n, 0, DETAIL_TEXTURE_HEIGHT/2, mPaint);
-            return bitmap;
-        }
-    };
-
-    @Override
-    public CharSequence onCreateDescription() {
-        return getText(R.string.carousel_test_activity_description);
-    }
-
-    private Runnable mAddCardRunnable = new Runnable() {
-        public void run() {
-            if (mView.getCardCount() < TOTAL_CARDS) {
-                mView.createCards(mView.getCardCount() + 1);
-                mView.postDelayed(mAddCardRunnable, 2000);
-            }
-        }
-    };
-
-    void postMessage(final CharSequence title, final CharSequence msg) {
-        runOnUiThread(new Runnable() {
-            public void run() {
-                new AlertDialog.Builder(CarouselTestActivity.this)
-                    .setTitle(title)
-                    .setMessage(msg)
-                    .setPositiveButton("OK", null)
-                    .create()
-                    .show();
-            }
-        });
-    }
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        setContentView(R.layout.carousel_test);
-        mView = (CarouselView) findViewById(R.id.carousel);
-        mView.getHolder().setFormat(PixelFormat.RGBA_8888);
-        mPaint.setColor(0xffffffff);
-        final Resources res = getResources();
-
-        mHelper = new LocalCarouselViewHelper(this);
-        mHelper.setCarouselView(mView);
-        mView.setSlotCount(CARD_SLOTS);
-        mView.createCards(INCREMENTAL_ADD ? 1: TOTAL_CARDS);
-        mView.setVisibleSlots(SLOTS_VISIBLE);
-        mView.setStartAngle((float) -(2.0f*Math.PI * 5 / CARD_SLOTS));
-        mBorder = BitmapFactory.decodeResource(res, R.drawable.border);
-        mView.setDefaultBitmap(mBorder);
-        mView.setLoadingBitmap(mBorder);
-        mView.setBackgroundColor(0.25f, 0.25f, 0.5f, 0.5f);
-        mView.setRezInCardCount(3.0f);
-        mView.setFadeInDuration(250);
-        mView.setVisibleDetails(VISIBLE_DETAIL_COUNT);
-        mView.setDragModel(CarouselView.DRAG_MODEL_PLANE);
-        if (INCREMENTAL_ADD) {
-            mView.postDelayed(mAddCardRunnable, 2000);
-        }
-
-        mGlossyOverlay = BitmapFactory.decodeResource(res, R.drawable.glossy_overlay);
-    }
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-        mHelper.onResume();
-    }
-
-    @Override
-    protected void onPause() {
-        super.onPause();
-        mHelper.onPause();
-    }
-
-}
diff --git a/carousel/test/src/com/android/carouseltest/MusicDemoActivity.java b/carousel/test/src/com/android/carouseltest/MusicDemoActivity.java
deleted file mode 100644
index 0ed4993..0000000
--- a/carousel/test/src/com/android/carouseltest/MusicDemoActivity.java
+++ /dev/null
@@ -1,113 +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.carouseltest;
-
-import com.android.ex.carousel.CarouselView;
-import com.android.ex.carousel.CarouselViewHelper;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.os.Bundle;
-import android.util.Log;
-
-public class MusicDemoActivity extends Activity {
-    private static final String TAG = "MusicDemoActivity";
-    private static final int CD_GEOMETRY = R.raw.book;
-    private static final int VISIBLE_SLOTS = 7;
-    private static final int CARD_SLOTS = 56;
-    private static final int TOTAL_CARDS = 10000;
-    private CarouselView mView;
-    private int mImageResources[] = {
-        R.drawable.emo_im_angel,
-        R.drawable.emo_im_cool,
-        R.drawable.emo_im_crying,
-        R.drawable.emo_im_foot_in_mouth,
-        R.drawable.emo_im_happy,
-        R.drawable.emo_im_kissing,
-        R.drawable.emo_im_laughing,
-        R.drawable.emo_im_lips_are_sealed,
-        R.drawable.emo_im_money_mouth,
-        R.drawable.emo_im_sad,
-        R.drawable.emo_im_surprised,
-        R.drawable.emo_im_tongue_sticking_out,
-        R.drawable.emo_im_undecided,
-        R.drawable.emo_im_winking,
-        R.drawable.emo_im_wtf,
-        R.drawable.emo_im_yelling
-    };
-
-    private LocalCarouselViewHelper mHelper;
-
-    class LocalCarouselViewHelper extends CarouselViewHelper {
-
-        LocalCarouselViewHelper(Context context) {
-            super(context);
-        }
-
-        @Override
-        public void onCardSelected(int id) {
-            Log.v(TAG, "Yay, item " + id + " was selected!");
-        }
-
-        @Override
-        public Bitmap getTexture(int n) {
-            return BitmapFactory.decodeResource(getResources(),
-                    mImageResources[n % mImageResources.length]);
-        }
-
-        @Override
-        public Bitmap getDetailTexture(int n) {
-            return null;
-        }
-    };
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        final Resources res = getResources();
-        setContentView(R.layout.music_demo);
-        mView = (CarouselView) findViewById(R.id.carousel);
-        mHelper = new LocalCarouselViewHelper(this);
-        mHelper.setCarouselView(mView);
-        mView.setSlotCount(CARD_SLOTS);
-        mView.createCards(TOTAL_CARDS);
-        mView.setVisibleSlots(VISIBLE_SLOTS);
-        mView.setStartAngle((float) -(2.0f*Math.PI * 5 / CARD_SLOTS));
-        mView.setDefaultBitmap(BitmapFactory.decodeResource(res, R.drawable.wait));
-        mView.setLoadingBitmap(BitmapFactory.decodeResource(res, R.drawable.blank_album));
-        mView.setBackgroundBitmap(BitmapFactory.decodeResource(res, R.drawable.background));
-        mView.setDefaultGeometry(CD_GEOMETRY);
-        mView.setFadeInDuration(250);
-        mView.setRezInCardCount(3.0f);
-        mView.setForceBlendCardsWithZ(false);
-    }
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-        mHelper.onResume();
-    }
-
-    @Override
-    protected void onPause() {
-        super.onPause();
-        mHelper.onPause();
-    }
-}
diff --git a/carousel/test/src/com/android/carouseltest/MyCarouselView.java b/carousel/test/src/com/android/carouseltest/MyCarouselView.java
deleted file mode 100644
index 973a9bc..0000000
--- a/carousel/test/src/com/android/carouseltest/MyCarouselView.java
+++ /dev/null
@@ -1,49 +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.carouseltest;
-
-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, CarouselController controller) {
-        this(context, null, controller);
-    }
-
-    public MyCarouselView(Context context, AttributeSet attrs) {
-        this(context, attrs, new CarouselController());
-    }
-
-    public MyCarouselView(Context context, AttributeSet attrs, CarouselController controller) {
-        super(context, attrs, controller);
-    }
-
-    public Info getRenderScriptInfo() {
-        return new Info(R.raw.carousel);
-    }
-
-    @Override
-    public boolean interpretLongPressEvents() {
-        return true;
-    }
-
-}
diff --git a/carousel/test/src/com/android/carouseltest/TaskSwitcherActivity.java b/carousel/test/src/com/android/carouseltest/TaskSwitcherActivity.java
deleted file mode 100644
index 0a76ecc..0000000
--- a/carousel/test/src/com/android/carouseltest/TaskSwitcherActivity.java
+++ /dev/null
@@ -1,300 +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.carouseltest;
-
-import java.util.ArrayList;
-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;
-import android.app.ActivityManager;
-import android.app.IThumbnailReceiver;
-import android.app.ActivityManager.RunningTaskInfo;
-import android.content.ActivityNotFoundException;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Bitmap.Config;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.util.Log;
-import android.view.View;
-
-public class TaskSwitcherActivity extends Activity {
-    private static final String TAG = "TaskSwitcherActivity";
-    private static final int CARD_SLOTS = 56;
-    private static final int MAX_TASKS = 20;
-    private static final int VISIBLE_SLOTS = 7;
-    protected static final boolean DBG = false;
-    private ActivityManager mActivityManager;
-    private List<RunningTaskInfo> mRunningTaskList;
-    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;
-
-    static class ActivityDescription {
-        int id;
-        Bitmap thumbnail;
-        Drawable icon;
-        CharSequence label;
-        CharSequence description;
-        Intent intent;
-        Matrix matrix;
-
-        public ActivityDescription(Bitmap _thumbnail,
-                Drawable _icon, String _label, String _desc, int _id)
-        {
-            thumbnail = _thumbnail;
-            icon = _icon;
-            label = _label;
-            description = _desc;
-            id = _id;
-        }
-
-        public void clear() {
-            icon = null;
-            thumbnail = null;
-            label = null;
-            description = null;
-            intent = null;
-            matrix = null;
-            id = -1;
-        }
-    };
-
-    private ActivityDescription findActivityDescription(int id) {
-        for (int i = 0; i < mActivityDescriptions.size(); i++) {
-            ActivityDescription item = mActivityDescriptions.get(i);
-            if (item != null && item.id == id) {
-                return item;
-            }
-        }
-        return null;
-    }
-
-    class LocalCarouselViewHelper extends CarouselViewHelper {
-        private static final int DETAIL_TEXTURE_WIDTH = 256;
-        private static final int DETAIL_TEXTURE_HEIGHT = 80;
-        private Paint mPaint = new Paint();
-        private DetailTextureParameters mDetailTextureParameters
-                = new DetailTextureParameters(5.0f, 5.0f);
-
-        public LocalCarouselViewHelper(Context context) {
-            super(context);
-        }
-
-        @Override
-        public DetailTextureParameters getDetailTextureParameters(int id) {
-            return mDetailTextureParameters;
-        }
-
-        @Override
-        public void onCardSelected(int n) {
-            if (n < mActivityDescriptions.size()) {
-                ActivityDescription item = mActivityDescriptions.get(n);
-                // prepare a launch intent and send it
-                if (item.intent != null) {
-                    item.intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY);
-                    try {
-                        Log.v(TAG, "Starting intent " + item.intent);
-                        startActivity(item.intent);
-                        overridePendingTransition(R.anim.zoom_enter, R.anim.zoom_exit);
-                    } catch (ActivityNotFoundException e) {
-                        Log.w("Recent", "Unable to launch recent task", e);
-                    }
-                    finish();
-                }
-            }
-        }
-
-        @Override
-        public Bitmap getTexture(int n) {
-            ActivityDescription desc = mActivityDescriptions.get(n);
-            Bitmap bitmap = desc.thumbnail == null ? mBlankBitmap : desc.thumbnail;
-            return bitmap;
-        }
-
-        @Override
-        public Bitmap getDetailTexture(int n) {
-            Bitmap bitmap = null;
-            if (n < mActivityDescriptions.size()) {
-                ActivityDescription item = mActivityDescriptions.get(n);
-                bitmap = Bitmap.createBitmap(DETAIL_TEXTURE_WIDTH, DETAIL_TEXTURE_HEIGHT,
-                    Bitmap.Config.ARGB_8888);
-                Canvas canvas = new Canvas(bitmap);
-                canvas.drawARGB(128,128,128,255);
-                mPaint.setTextSize(15.0f);
-                mPaint.setColor(0xffffffff);
-                mPaint.setAntiAlias(true);
-                canvas.drawText(item.label.toString(),0, DETAIL_TEXTURE_HEIGHT/2, mPaint);
-            }
-            return bitmap;
-        }
-    };
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        final Resources res = getResources();
-        final View decorView = getWindow().getDecorView();
-
-        mController = new CarouselController();
-        mView = new MyCarouselView(this, mController);
-        mHelper = new LocalCarouselViewHelper(this);
-        mHelper.setCarouselView(mView);
-        mView.setSlotCount(CARD_SLOTS);
-        mView.setVisibleSlots(VISIBLE_SLOTS);
-        mView.createCards(1);
-        mView.setStartAngle((float) -(2.0f*Math.PI * 5 / CARD_SLOTS));
-        mView.setDefaultBitmap(BitmapFactory.decodeResource(res, R.drawable.wait));
-        mView.setLoadingBitmap(BitmapFactory.decodeResource(res, R.drawable.wait));
-        mView.setBackgroundColor(0.1f, 0.1f, 0.1f, 1.0f);
-
-        mActivityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
-        mPortraitMode = decorView.getHeight() > decorView.getWidth();
-
-        refresh();
-        setContentView(mView);
-    }
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-        mHelper.onResume();
-        refresh();
-    }
-
-    @Override
-    protected void onPause() {
-        super.onPause();
-        mHelper.onPause();
-    }
-
-    @Override
-    public void onConfigurationChanged(Configuration newConfig) {
-        super.onConfigurationChanged(newConfig);
-        mPortraitMode = newConfig.orientation == Configuration.ORIENTATION_PORTRAIT;
-        Log.v(TAG, "CONFIG CHANGE, mPortraitMode = " + mPortraitMode);
-        refresh();
-    }
-
-    void updateRunningTasks() {
-        mRunningTaskList = mActivityManager.getRunningTasks(MAX_TASKS + 2);
-        Log.v(TAG, "Portrait: " + mPortraitMode);
-        for (RunningTaskInfo r : mRunningTaskList) {
-            if (r.thumbnail != null) {
-                int thumbWidth = r.thumbnail.getWidth();
-                int thumbHeight = r.thumbnail.getHeight();
-                Log.v(TAG, "Got thumbnail " + thumbWidth + "x" + thumbHeight);
-                ActivityDescription desc = findActivityDescription(r.id);
-                if (desc != null) {
-                    desc.thumbnail = r.thumbnail;
-                    desc.description = r.description;
-                    if ((mPortraitMode && thumbWidth > thumbHeight)
-                            || (!mPortraitMode && thumbWidth < thumbHeight)) {
-                        Matrix matrix = new Matrix();
-                        matrix.setRotate(90.0f, (float) thumbWidth / 2, (float) thumbHeight / 2);
-                        desc.matrix = matrix;
-                    }
-                } else {
-                    Log.v(TAG, "Couldn't find ActivityDesc for id=" + r.id);
-                }
-            } else {
-                Log.v(TAG, "*** RUNNING THUMBNAIL WAS NULL ***");
-            }
-        }
-        // HACK refresh carousel
-        mView.createCards(mActivityDescriptions.size());
-    }
-
-    private void updateRecentTasks() {
-        final PackageManager pm = getPackageManager();
-        final ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
-
-        final List<ActivityManager.RecentTaskInfo> recentTasks =
-                am.getRecentTasks(MAX_TASKS + 2, ActivityManager.RECENT_IGNORE_UNAVAILABLE);
-
-        ActivityInfo homeInfo = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME)
-                    .resolveActivityInfo(pm, 0);
-
-        //IconUtilities iconUtilities = new IconUtilities(this);
-
-        int numTasks = recentTasks.size();
-        mActivityDescriptions.clear();
-        for (int i = 1, index = 0; i < numTasks && (index < MAX_TASKS + 2); ++i) {
-            final ActivityManager.RecentTaskInfo recentInfo = recentTasks.get(i);
-
-            Intent intent = new Intent(recentInfo.baseIntent);
-            if (recentInfo.origActivity != null) {
-                intent.setComponent(recentInfo.origActivity);
-            }
-
-            // Skip the current home activity.
-            if (homeInfo != null
-                    && homeInfo.packageName.equals(intent.getComponent().getPackageName())
-                    && homeInfo.name.equals(intent.getComponent().getClassName())) {
-                continue;
-            }
-
-            intent.setFlags((intent.getFlags()&~Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
-                    | Intent.FLAG_ACTIVITY_NEW_TASK);
-            final ResolveInfo resolveInfo = pm.resolveActivity(intent, 0);
-            if (resolveInfo != null) {
-                final ActivityInfo info = resolveInfo.activityInfo;
-                final String title = info.loadLabel(pm).toString();
-                Drawable icon = info.loadIcon(pm);
-
-                int id = recentInfo.id;
-                if (id != -1 && title != null && title.length() > 0 && icon != null) {
-                    //icon = iconUtilities.createIconDrawable(icon);
-                    ActivityDescription item = new ActivityDescription(null, icon, title, null, id);
-                    item.intent = intent;
-                    mActivityDescriptions.add(item);
-                    Log.v(TAG, "Added item[" + index + "], id=" + item.id);
-                    ++index;
-                } else {
-                    Log.v(TAG, "SKIPPING item " + id);
-                }
-            }
-        }
-    }
-
-    private void refresh() {
-        updateRecentTasks();
-        updateRunningTasks();
-        mView.createCards(mActivityDescriptions.size());
-    }
-}