cts_audio work: initial code
- volume calibration and THD test case work tuned.
- 59 unit tests pass
- local audio playback / recording works : uses tinyalsa
- host to device ptorocol in host side implemented / tested (with loopback)
- device side recording / playback works for test cases / test_io.xml
- python processing baseline added.
- spectrum algorithm implementated: calculate Transfer Function of device
  over host and check if amplitudes are within margain. Needs parameter tuning
- spectrum test needs some improvements due to the non-flat response from
  ref microphone.
- build is enabled only for linux host except the client code

Change-Id: I8453ac72b6fce7ddbfee7e2cc05207f09f2b3d88
diff --git a/suite/audio_quality/test/Android.mk b/suite/audio_quality/test/Android.mk
new file mode 100644
index 0000000..9e32557
--- /dev/null
+++ b/suite/audio_quality/test/Android.mk
@@ -0,0 +1,41 @@
+#
+# Copyright (C) 2012 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.
+#
+
+# build only for linux
+ifeq ($(HOST_OS),linux)
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+LOCAL_CPP_EXTENSION := .cpp
+LOCAL_MODULE_TAGS := optional
+LOCAL_SRC_FILES := $(patsubst ./%,%, $(shell cd $(LOCAL_PATH); \
+  find . -name "*.cpp" -and -not -name ".*"))
+#LOCAL_SRC_FILES := 	AudioRecordPlayTest.cpp
+
+#$(info $(LOCAL_SRC_FILES))
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../lib/include $(LOCAL_PATH)/../lib/src external/gtest/include \
+    external/tinyalsa/include/  libcore/include
+LOCAL_STATIC_LIBRARIES := libutils libgtest_host libgtest_main_host  liblog libcutils libtinyalsa \
+    libtinyxml
+# need to keep everything in libcts_.. Otherwise, linker will drop some
+# functions and linker error happens
+LOCAL_WHOLE_STATIC_LIBRARIES := libcts_audio_quality
+LOCAL_CFLAGS:= -g -fno-exceptions
+LOCAL_LDFLAGS:= -g -lrt -ldl -lstdc++ -lm -fno-exceptions
+LOCAL_MODULE:= cts_audio_quality_test
+include $(BUILD_HOST_EXECUTABLE)
+
+endif # linux
diff --git a/suite/audio_quality/test/AudioHardwareTest.cpp b/suite/audio_quality/test/AudioHardwareTest.cpp
new file mode 100644
index 0000000..35d750b
--- /dev/null
+++ b/suite/audio_quality/test/AudioHardwareTest.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#include <gtest/gtest.h>
+#include <audio/AudioHardware.h>
+#include <task/TaskAll.h>
+
+
+class AudioHardwareTest : public testing::Test {
+
+};
+
+TEST_F(AudioHardwareTest, DetectTest) {
+    int hwId = AudioHardware::detectAudioHw();
+    ASSERT_TRUE(hwId >= 0);
+}
+
+TEST_F(AudioHardwareTest, LocalFactoryTest) {
+    android::sp<AudioHardware> playback = AudioHardware::createAudioHw(true, true);
+    ASSERT_TRUE(playback.get() != NULL);
+    android::sp<AudioHardware> recording = AudioHardware::createAudioHw(true, false);
+    ASSERT_TRUE(recording.get() != NULL);
+}
+
+TEST_F(AudioHardwareTest, RemoteFactoryTest) {
+    TaskCase* testCase = new TaskCase();
+    ASSERT_TRUE(testCase != NULL);
+    android::sp<AudioHardware> playback = AudioHardware::createAudioHw(false, true, testCase);
+    ASSERT_TRUE(playback.get() != NULL);
+    android::sp<AudioHardware> recording = AudioHardware::createAudioHw(false, false, testCase);
+    ASSERT_TRUE(recording.get() != NULL);
+    delete testCase;
+}
diff --git a/suite/audio_quality/test/AudioLocalTest.cpp b/suite/audio_quality/test/AudioLocalTest.cpp
new file mode 100644
index 0000000..b38c44d
--- /dev/null
+++ b/suite/audio_quality/test/AudioLocalTest.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+#include <unistd.h>
+
+#include <gtest/gtest.h>
+#include <utils/threads.h>
+#include <utils/StrongPointer.h>
+
+#include <audio/AudioLocal.h>
+#include <audio/Buffer.h>
+#include <Log.h>
+
+#include "AudioPlayTestCommon.h"
+
+class AudioPlayerDummy: public AudioLocal {
+public:
+    AudioHardware::SamplingRate mSamplingRate;
+    android::sp<Buffer> mBufferPassed;
+    bool mPrepareCalled;
+    bool mdoStartPlaybackOrRecordCalled;
+    bool mdoContinuePlaybackOrRecordCalled;
+    bool mdoStopCalled;
+    int mPlaybackUnit;
+
+    AudioPlayerDummy()
+        : mSamplingRate(AudioHardware::ESamplingRateInvald),
+          mPrepareCalled(false),
+          mdoStartPlaybackOrRecordCalled(false),
+          mdoContinuePlaybackOrRecordCalled(false),
+          mdoStopCalled(false)
+    {
+
+    }
+
+    virtual bool doPrepare(AudioHardware::SamplingRate samplingRate, int samplesInOneGo) {
+        mPlaybackUnit = samplesInOneGo * 4;
+        LOGV("doPrepare");
+        return true;
+    };
+
+    virtual bool doPlaybackOrRecord(android::sp<Buffer>& buffer) {
+        buffer->increaseHandled(mPlaybackUnit);
+        return true;
+    };
+
+    virtual void doStop() {
+        LOGV("doStop");
+    };
+
+
+};
+
+class AudioLocalTest : public AudioPlayTestCommon {
+public:
+    virtual ~AudioLocalTest() {};
+
+protected:
+    android::sp<AudioHardware> createAudioHw() {
+        android::sp<AudioHardware> hw(new AudioPlayerDummy());
+        return hw;
+    }
+};
+
+TEST_F(AudioLocalTest, PlayAllTest) {
+    playAll(1);
+}
+
+TEST_F(AudioLocalTest, PlayAllRepeatTest) {
+    playAll(4);
+}
+
+TEST_F(AudioLocalTest, StartStopTest) {
+    repeatPlayStop();
+}
+
+TEST_F(AudioLocalTest, WrongUsageTest) {
+    playWrongUsage();
+}
+
diff --git a/suite/audio_quality/test/AudioPlayTestCommon.h b/suite/audio_quality/test/AudioPlayTestCommon.h
new file mode 100644
index 0000000..96f129c
--- /dev/null
+++ b/suite/audio_quality/test/AudioPlayTestCommon.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#ifndef CTSAUDIO_AUDIOPLAYTESTCOMMON_H
+#define CTSAUDIO_AUDIOPLAYTESTCOMMON_H
+
+#include <gtest/gtest.h>
+#include <utils/threads.h>
+#include <utils/StrongPointer.h>
+
+#include <audio/AudioHardware.h>
+#include <audio/AudioPlaybackLocal.h>
+#include <audio/AudioRecordingLocal.h>
+#include <audio/AudioSignalFactory.h>
+#include <audio/AudioLocal.h>
+#include <audio/Buffer.h>
+
+
+#include <Log.h>
+
+
+class AudioPlayTestCommon : public testing::Test {
+protected:
+    android::sp<Buffer> mBuffer;
+    android::sp<AudioHardware> mAudioHw;
+
+    static const int MAX_POSITIVE_AMPLITUDE = 1000;
+    static const int SIGNAL_FREQ = 1000;
+    static const int SIGNAL_LENGTH = AudioHardware::SAMPLES_PER_ONE_GO * 2;
+    static const int DEFAULT_VOLUME = 10;
+
+protected:
+    virtual ~AudioPlayTestCommon() {
+        LOGV("~AudioPlayTestCommon");
+    }
+    virtual void SetUp() {
+        mAudioHw = createAudioHw();
+        ASSERT_TRUE(mAudioHw.get() != NULL);
+        mBuffer = AudioSignalFactory::generateSineWave(AudioHardware::E2BPS,
+                MAX_POSITIVE_AMPLITUDE, AudioHardware::ESampleRate_44100,
+                SIGNAL_FREQ, SIGNAL_LENGTH);
+        ASSERT_TRUE(mBuffer.get() != NULL);
+    }
+
+    virtual void TearDown() {
+        LOGV("AudioPlayTestCommon::TearDown");
+        mAudioHw->stopPlaybackOrRecord(); // this stops the thread
+        mAudioHw.clear();
+    }
+
+    void playAll(int numberRepetition) {
+        ASSERT_TRUE(mAudioHw->prepare(AudioHardware::ESampleRate_44100, DEFAULT_VOLUME));
+        ASSERT_TRUE(mAudioHw->startPlaybackOrRecord(mBuffer, numberRepetition));
+        ASSERT_TRUE(mAudioHw->waitForCompletion());
+        mAudioHw->stopPlaybackOrRecord();
+        LOGV("size %d, handled %d", mBuffer->getSize(), mBuffer->amountHandled());
+        ASSERT_TRUE(mBuffer->amountHandled() == mBuffer->getSize());
+    }
+
+    void repeatPlayStop() {
+        for (int i = 0; i < 2; i++) {
+            ASSERT_TRUE(mAudioHw->prepare(AudioHardware::ESampleRate_44100, DEFAULT_VOLUME));
+            mBuffer->restart();
+            ASSERT_TRUE(mAudioHw->startPlaybackOrRecord(mBuffer, 10));
+            mAudioHw->stopPlaybackOrRecord();
+        }
+    }
+
+    void playWrongUsage() {
+        ASSERT_FALSE(mAudioHw->startPlaybackOrRecord(mBuffer));
+        ASSERT_TRUE(mAudioHw->prepare(AudioHardware::ESampleRate_44100, DEFAULT_VOLUME));
+        playAll(1);
+    }
+
+    virtual android::sp<AudioHardware> createAudioHw() = 0;
+};
+
+#endif // CTSAUDIO_AUDIOPLAYTESTCOMMON_H
diff --git a/suite/audio_quality/test/AudioPlaybackLocalTest.cpp b/suite/audio_quality/test/AudioPlaybackLocalTest.cpp
new file mode 100644
index 0000000..896d01c
--- /dev/null
+++ b/suite/audio_quality/test/AudioPlaybackLocalTest.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+#include <unistd.h>
+
+#include <gtest/gtest.h>
+#include <utils/threads.h>
+#include <utils/StrongPointer.h>
+
+#include <audio/AudioHardware.h>
+#include <GenericFactory.h>
+#include <audio/AudioPlaybackLocal.h>
+
+#include <Log.h>
+
+#include "AudioPlayTestCommon.h"
+
+class AudioPlaybackLocalTest : public AudioPlayTestCommon {
+public:
+    virtual ~AudioPlaybackLocalTest() {};
+protected:
+
+    android::sp<AudioHardware> createAudioHw() {
+        return AudioHardware::createAudioHw(true, true);
+    }
+};
+
+
+TEST_F(AudioPlaybackLocalTest, PlayAllTest) {
+    playAll(1);
+}
+
+TEST_F(AudioPlaybackLocalTest, PlayAllRepeatTest) {
+    playAll(4);
+}
+
+TEST_F(AudioPlaybackLocalTest, StartStopTest) {
+    repeatPlayStop();
+}
+
+TEST_F(AudioPlaybackLocalTest, WrongUsageTest) {
+    playWrongUsage();
+}
+
+
diff --git a/suite/audio_quality/test/AudioRecordPlayLocalTest.cpp b/suite/audio_quality/test/AudioRecordPlayLocalTest.cpp
new file mode 100644
index 0000000..3a94d06
--- /dev/null
+++ b/suite/audio_quality/test/AudioRecordPlayLocalTest.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#include "AudioRecordPlayTestCommon.h"
+
+#include <Log.h>
+
+class AudioRecordPlayLocalTest: public AudioRecordPlayTestCommon {
+public:
+    virtual ~AudioRecordPlayLocalTest() {};
+protected:
+    android::sp<AudioHardware> createRecordingHw() {
+        return AudioHardware::createAudioHw(true, false);
+    };
+
+    android::sp<AudioHardware> createPlaybackHw() {
+        return AudioHardware::createAudioHw(true, true);
+    }
+};
+
+
+
+TEST_F(AudioRecordPlayLocalTest, PlayAndRecordTest) {
+    PlayAndRecord(4);
+}
+
+
diff --git a/suite/audio_quality/test/AudioRecordPlayTestCommon.h b/suite/audio_quality/test/AudioRecordPlayTestCommon.h
new file mode 100644
index 0000000..28bc0a6
--- /dev/null
+++ b/suite/audio_quality/test/AudioRecordPlayTestCommon.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+
+#ifndef CTSAUDIO_AUDIORECORDPLAYTESTCOMMON_H
+#define CTSAUDIO_AUDIORECORDPLAYTESTCOMMON_H
+
+#include <gtest/gtest.h>
+#include <utils/threads.h>
+#include <utils/StrongPointer.h>
+
+#include <audio/AudioHardware.h>
+#include <audio/AudioPlaybackLocal.h>
+#include <audio/AudioRecordingLocal.h>
+#include <audio/AudioSignalFactory.h>
+#include <audio/AudioLocal.h>
+#include <audio/Buffer.h>
+#include <Log.h>
+
+class AudioRecordPlayTestCommon : public testing::Test {
+protected:
+    android::sp<Buffer> mBufferRecording;
+    android::sp<Buffer> mBufferPlayback;
+    android::sp<AudioHardware> mAudioRecordingHw;
+    android::sp<AudioHardware> mAudioPlaybackHw;
+
+    static const int MAX_POSITIVE_AMPLITUDE = 10000;
+    static const int SIGNAL_FREQ = 1000;
+    static const int NUMBER_SAMPLES = AudioHardware::SAMPLES_PER_ONE_GO * 4;
+    static const int DEFAULT_VOLUME = 10;
+protected:
+    virtual void SetUp() {
+        mAudioPlaybackHw = createPlaybackHw();
+        ASSERT_TRUE(mAudioPlaybackHw.get() != NULL);
+        mAudioRecordingHw = createRecordingHw();
+        ASSERT_TRUE(mAudioRecordingHw.get() != NULL);
+        mBufferPlayback = AudioSignalFactory::generateSineWave(AudioHardware::E2BPS,
+                MAX_POSITIVE_AMPLITUDE, AudioHardware::ESampleRate_44100,
+                SIGNAL_FREQ, NUMBER_SAMPLES);
+        ASSERT_TRUE(mBufferPlayback.get() != NULL);
+        mBufferRecording = new Buffer(NUMBER_SAMPLES * 4, NUMBER_SAMPLES * 4);
+        ASSERT_TRUE(mBufferRecording.get() != NULL);
+    }
+
+    virtual void TearDown() {
+        mAudioRecordingHw->stopPlaybackOrRecord();
+        mAudioPlaybackHw->stopPlaybackOrRecord();
+        mAudioRecordingHw.clear();
+        mAudioPlaybackHw.clear();
+    }
+
+    void PlayAndRecord(int numberRepetition) {
+        ASSERT_TRUE(mAudioPlaybackHw->prepare(AudioHardware::ESampleRate_44100, DEFAULT_VOLUME));
+        ASSERT_TRUE(mAudioRecordingHw->prepare(AudioHardware::ESampleRate_44100, DEFAULT_VOLUME));
+        ASSERT_TRUE(mAudioRecordingHw->startPlaybackOrRecord(mBufferRecording,
+                numberRepetition));
+        ASSERT_TRUE(mAudioPlaybackHw->startPlaybackOrRecord(mBufferPlayback,
+                numberRepetition));
+
+        ASSERT_TRUE(mAudioRecordingHw->waitForCompletion());
+        ASSERT_TRUE(mAudioPlaybackHw->waitForCompletion());
+        mAudioPlaybackHw->stopPlaybackOrRecord();
+        mAudioRecordingHw->stopPlaybackOrRecord();
+        LOGV("Audio playback buffer size %d, handled %d", mBufferPlayback->getSize(),
+                mBufferPlayback->amountHandled());
+        ASSERT_TRUE(mBufferPlayback->amountHandled() == mBufferPlayback->getSize());
+        LOGV("Audio recording buffer size %d, handled %d", mBufferRecording->getSize(),
+                mBufferRecording->amountHandled());
+        ASSERT_TRUE(mBufferRecording->amountHandled() == mBufferRecording->getSize());
+    }
+
+    virtual android::sp<AudioHardware> createRecordingHw() = 0;
+    virtual android::sp<AudioHardware> createPlaybackHw() = 0;
+};
+
+
+
+
+#endif // CTSAUDIO_AUDIORECORDPLAYTESTCOMMON_H
diff --git a/suite/audio_quality/test/AudioRecordingLocalTest.cpp b/suite/audio_quality/test/AudioRecordingLocalTest.cpp
new file mode 100644
index 0000000..bb9f8ba
--- /dev/null
+++ b/suite/audio_quality/test/AudioRecordingLocalTest.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+#include <unistd.h>
+
+#include <gtest/gtest.h>
+#include <utils/threads.h>
+#include <utils/StrongPointer.h>
+
+#include <audio/AudioHardware.h>
+#include <GenericFactory.h>
+#include <audio/AudioRecordingLocal.h>
+
+#include <Log.h>
+
+#include "AudioPlayTestCommon.h"
+
+class AudioRecordingLocalTest : public AudioPlayTestCommon {
+public:
+    virtual ~AudioRecordingLocalTest() {};
+protected:
+
+    android::sp<AudioHardware> createAudioHw() {
+        return AudioHardware::createAudioHw(true, false);
+    }
+};
+
+
+TEST_F(AudioRecordingLocalTest, PlayAllTest) {
+    playAll(1);
+}
+
+TEST_F(AudioRecordingLocalTest, PlayAllRepeatTest) {
+    playAll(4);
+}
+
+TEST_F(AudioRecordingLocalTest, StartStopTest) {
+    repeatPlayStop();
+}
+
+TEST_F(AudioRecordingLocalTest, WrongUsageTest) {
+    playWrongUsage();
+}
+
diff --git a/suite/audio_quality/test/AudioSignalFactoryTest.cpp b/suite/audio_quality/test/AudioSignalFactoryTest.cpp
new file mode 100644
index 0000000..62ff900
--- /dev/null
+++ b/suite/audio_quality/test/AudioSignalFactoryTest.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+#include <stdint.h>
+
+#include <gtest/gtest.h>
+
+#include <audio/AudioSignalFactory.h>
+
+class AudioSignalFactoryTest: public testing::Test {
+protected:
+
+    void testSignalBasic(android::sp<Buffer>& buffer, int maxPositive,
+            AudioHardware::SamplingRate samplingRate, int signalFreq, int samples) {
+        ASSERT_TRUE(buffer->getSize() == (unsigned int)(AudioHardware::E2BPS * 2 * samples));
+        int16_t* data = reinterpret_cast<int16_t*>(buffer->getData());
+        for(int i = 0; i < samples; i++) {
+            ASSERT_TRUE(*data <= maxPositive);
+            ASSERT_TRUE(*data >= -maxPositive);
+            data++;
+            ASSERT_TRUE(*data <= maxPositive);
+            ASSERT_TRUE(*data >= -maxPositive);
+            data++;
+        }
+    }
+};
+
+TEST_F(AudioSignalFactoryTest, SineTest) {
+    const int maxPositive = 1000;
+    const int signalFreq = AudioHardware::ESampleRate_44100/100;
+    const int samples = 8192 * 10;
+    android::sp<Buffer> buffer = AudioSignalFactory::generateSineWave(AudioHardware::E2BPS,
+            maxPositive, AudioHardware::ESampleRate_44100, signalFreq, samples);
+    testSignalBasic(buffer, maxPositive, AudioHardware::ESampleRate_44100, signalFreq, samples);
+}
+
+TEST_F(AudioSignalFactoryTest, WhiteNoiseTest) {
+    const int maxPositive = 1000;
+    const int signalFreq = AudioHardware::ESampleRate_44100/100;
+    const int samples = 8192 * 10;
+    android::sp<Buffer> buffer = AudioSignalFactory::generateWhiteNoise(AudioHardware::E2BPS,
+            maxPositive, samples);
+    testSignalBasic(buffer, maxPositive, AudioHardware::ESampleRate_44100, signalFreq, samples);
+}
+
diff --git a/suite/audio_quality/test/BufferTest.cpp b/suite/audio_quality/test/BufferTest.cpp
new file mode 100644
index 0000000..2c7b20e
--- /dev/null
+++ b/suite/audio_quality/test/BufferTest.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#include <stdint.h>
+#include <gtest/gtest.h>
+
+#include <UniquePtr.h>
+
+#include "audio/Buffer.h"
+
+
+class BufferTest : public testing::Test {
+public:
+
+    virtual void SetUp() {
+
+    }
+
+    virtual void TearDown() {
+
+    }
+};
+
+
+TEST_F(BufferTest, saveLoadStereoTest) {
+    const int BUFFER_SIZE = 32;
+
+    UniquePtr<Buffer> buffer(new Buffer(BUFFER_SIZE, BUFFER_SIZE, true));
+    ASSERT_TRUE(buffer.get() != NULL);
+    int16_t* data = (int16_t*)buffer->getData();
+    ASSERT_TRUE(data != NULL);
+    for (int i = 0; i < BUFFER_SIZE/4; i++) {
+        data[2*i] = i;
+        data[2*i+1] = i;
+    }
+    android::String8 file("/tmp/cts_audio_temp");
+    ASSERT_TRUE(buffer->saveToFile(file));
+    file.append(".r2s");
+    UniquePtr<Buffer> bufferRead(Buffer::loadFromFile(file));
+    ASSERT_TRUE(bufferRead.get() != NULL);
+    ASSERT_TRUE(bufferRead->getSize() == (size_t)BUFFER_SIZE);
+    ASSERT_TRUE(bufferRead->isStereo());
+    int16_t* dataRead = (int16_t*)bufferRead->getData();
+    for (int i = 0; i < BUFFER_SIZE/4; i++) {
+        ASSERT_TRUE(data[2*i] == dataRead[2*i]);
+        ASSERT_TRUE(data[2*i+1] == dataRead[2*i+1]);
+    }
+}
+
+TEST_F(BufferTest, monoLTest) {
+    const int BUFFER_SIZE = 8;
+
+    UniquePtr<Buffer> buffer(new Buffer(BUFFER_SIZE, BUFFER_SIZE, true));
+    ASSERT_TRUE(buffer.get() != NULL);
+    int16_t* data = (int16_t*)buffer->getData();
+    ASSERT_TRUE(data != NULL);
+    for (int i = 0; i < BUFFER_SIZE/2; i++) {
+        data[i] = i;
+    }
+    UniquePtr<Buffer> bufferl(new Buffer(BUFFER_SIZE/2, BUFFER_SIZE/2, false));
+    ASSERT_TRUE(bufferl.get() != NULL);
+    data = (int16_t*)bufferl->getData();
+    ASSERT_TRUE(data != NULL);
+    for (int i = 0; i < BUFFER_SIZE/4; i++) {
+        data[i] = 2 * i;
+    }
+    buffer->changeToMono(Buffer::EKeepCh0);
+    ASSERT_TRUE((*buffer) == (*bufferl));
+}
diff --git a/suite/audio_quality/test/ClientInterfaceTest.cpp b/suite/audio_quality/test/ClientInterfaceTest.cpp
new file mode 100644
index 0000000..b72be9b
--- /dev/null
+++ b/suite/audio_quality/test/ClientInterfaceTest.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#include <utils/String8.h>
+
+#include <gtest/gtest.h>
+
+#include <audio/AudioSignalFactory.h>
+#include <ClientInterface.h>
+#include <ClientImpl.h>
+#include <GenericFactory.h>
+#include <audio/RemoteAudio.h>
+
+
+
+class ClientInterfaceTest : public testing::Test {
+protected:
+    ClientInterface* mClient;
+
+protected:
+    virtual void SetUp() {
+        GenericFactory factory;
+        mClient = factory.createClientInterface();
+        ASSERT_TRUE(mClient != NULL);
+        android::String8 dummyParam;
+        ASSERT_TRUE(mClient->init(dummyParam));
+    }
+
+    virtual void TearDown() {
+        delete mClient;
+        mClient = NULL;
+    }
+};
+
+TEST_F(ClientInterfaceTest, InitTest) {
+    // all done in SetUp
+}
+
+TEST_F(ClientInterfaceTest, PlayTest) {
+    ClientImpl* client = reinterpret_cast<ClientImpl*>(mClient);
+    android::sp<RemoteAudio>& audio(client->getAudio());
+    const int maxPositive = 10000;
+    const int signalFreq = AudioHardware::ESampleRate_44100/100;
+    const int samples = 8192*2;
+    android::sp<Buffer> buffer = AudioSignalFactory::generateSineWave(AudioHardware::E2BPS,
+            maxPositive, AudioHardware::ESampleRate_44100, signalFreq, samples);
+    int id;
+    android::String8 name("1");
+    ASSERT_TRUE(audio->downloadData(name, buffer, id));
+    ASSERT_TRUE(audio->startPlayback(true, AudioHardware::ESampleRate_44100,
+            AudioHardware::EModeVoice, 100, id, 1));
+    ASSERT_TRUE(audio->waitForPlaybackCompletion());
+    ASSERT_TRUE(id == audio->getDataId(name));
+    android::String8 name2("2");
+    ASSERT_TRUE(audio->getDataId(name2) < 0);
+}
+
+TEST_F(ClientInterfaceTest, RecordTest) {
+    ClientImpl* client = reinterpret_cast<ClientImpl*>(mClient);
+    android::sp<RemoteAudio>& audio(client->getAudio());
+    const int maxPositive = 10000;
+    const int signalFreq = AudioHardware::ESampleRate_44100 / 100;
+    const int samples = 44100 * 4;
+    android::sp<Buffer> buffer(new Buffer(samples * 2, samples * 2, false));
+
+    ASSERT_TRUE(audio->startRecording(false, AudioHardware::ESampleRate_44100,
+            AudioHardware::EModeVoice, 100, buffer));
+    ASSERT_TRUE(audio->waitForRecordingCompletion());
+    ASSERT_TRUE(buffer->amountHandled() == (samples * 2));
+}
diff --git a/suite/audio_quality/test/FileUtilTest.cpp b/suite/audio_quality/test/FileUtilTest.cpp
new file mode 100644
index 0000000..d79b2aa
--- /dev/null
+++ b/suite/audio_quality/test/FileUtilTest.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#include <stdint.h>
+#include <gtest/gtest.h>
+
+#include <UniquePtr.h>
+
+#include "Log.h"
+#include "FileUtil.h"
+
+
+class FileUtilTest : public testing::Test {
+public:
+
+};
+
+
+TEST_F(FileUtilTest, initTest) {
+    android::String8 dirPath;
+    ASSERT_TRUE(FileUtil::prepare(dirPath));
+    ASSERT_TRUE(dirPath.find("reports/") == 0);
+    LOGI("returned %s %d", dirPath.string(), dirPath.find("reports/"));
+    android::String8 dirPath2;
+    ASSERT_TRUE(FileUtil::prepare(dirPath2));
+    ASSERT_TRUE(dirPath == dirPath2);
+}
+
+
diff --git a/suite/audio_quality/test/LogTest.cpp b/suite/audio_quality/test/LogTest.cpp
new file mode 100644
index 0000000..421b904
--- /dev/null
+++ b/suite/audio_quality/test/LogTest.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#include <stdint.h>
+#include <gtest/gtest.h>
+
+#include <UniquePtr.h>
+
+#include "Log.h"
+
+
+
+class LogTest : public testing::Test {
+public:
+
+};
+
+
+TEST_F(LogTest, logTest) {
+    Log::LogLevel level = Log::Instance()->getLogLevel();
+
+    // following lines should match. no automatic test yet..
+    // TODO make it automatic?
+    Log::Instance()->setLogLevel(Log::ELogV);
+    printf("printf %d %d %d %d %d %d\n", 0, 1, 2, 3, 4, 5);
+    LOGD(  "logd   %d %d %d %d %d %d", 0, 1, 2, 3, 4, 5);
+    LOGV(  "logv   %d %d %d %d %d %d", 0, 1, 2, 3, 4, 5);
+    LOGI(  "logi   %d %d %d %d %d %d", 0, 1, 2, 3, 4, 5);
+    LOGW(  "logw   %d %d %d %d %d %d", 0, 1, 2, 3, 4, 5);
+    LOGE(  "loge   %d %d %d %d %d %d", 0, 1, 2, 3, 4, 5);
+
+    int64_t a = 0;
+    int64_t b = 1;
+    int64_t c = 2;
+    int64_t d = 3;
+    int64_t e = 4;
+    int64_t f = 5;
+    printf("printf %lld %lld %lld %lld %lld %lld\n", a, b, c, d, e, f);
+    LOGD(  "logd   %lld %lld %lld %lld %lld %lld", a, b, c, d, e, f);
+    LOGV(  "logv   %lld %lld %lld %lld %lld %lld", a, b, c, d, e, f);
+    LOGI(  "logi   %lld %lld %lld %lld %lld %lld", a, b, c, d, e, f);
+    LOGW(  "logw   %lld %lld %lld %lld %lld %lld", a, b, c, d, e, f);
+    LOGE(  "loge   %lld %lld %lld %lld %lld %lld", a, b, c, d, e, f);
+
+    Log::Instance()->setLogLevel(level);
+}
+
+
+
diff --git a/suite/audio_quality/test/MixerTest.cpp b/suite/audio_quality/test/MixerTest.cpp
new file mode 100644
index 0000000..308822c
--- /dev/null
+++ b/suite/audio_quality/test/MixerTest.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+#include <stdint.h>
+#include <gtest/gtest.h>
+
+#include <UniquePtr.h>
+#include <tinyalsa/asoundlib.h>
+#include <Log.h>
+#include <audio/AudioHardware.h>
+
+class MixerTest : public testing::Test {
+public:
+
+    virtual void SetUp() {
+
+    }
+
+    virtual void TearDown() {
+
+    }
+};
+
+
+TEST_F(MixerTest, tryTinyAlsaTest) {
+    int hwId = AudioHardware::detectAudioHw();
+    ASSERT_TRUE(hwId >= 0);
+    struct mixer* mixerp = mixer_open(hwId);
+    ASSERT_TRUE(mixerp != NULL);
+    int num_ctls = mixer_get_num_ctls(mixerp);
+    // no mixer control for MobilePre. If this assumption fails,
+    // mixer control should be added.
+    ASSERT_TRUE(num_ctls == 0);
+    for (int i = 0; i < num_ctls; i++) {
+        struct mixer_ctl* control = mixer_get_ctl(mixerp, i);
+        ASSERT_TRUE(control != NULL);
+        LOGI("Mixer control %s type %s value %d", mixer_ctl_get_name(control),
+                mixer_ctl_get_type_string(control), mixer_ctl_get_num_values(control));
+        free(control);
+    }
+    mixer_close(mixerp);
+}
+
diff --git a/suite/audio_quality/test/ModelBuilderTest.cpp b/suite/audio_quality/test/ModelBuilderTest.cpp
new file mode 100644
index 0000000..49a0c57
--- /dev/null
+++ b/suite/audio_quality/test/ModelBuilderTest.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+
+#include <gtest/gtest.h>
+#include <task/ModelBuilder.h>
+
+
+class ModelBuilderTest : public testing::Test {
+public:
+    ModelBuilder mModelBuilder;
+};
+
+TEST_F(ModelBuilderTest, ParsingCaseNoAttribTest) {
+    android::String8 xmlFile("test_description/test/no_attrib.xml");
+    TaskGeneric* testCase = mModelBuilder.parseTestDescriptionXml(xmlFile);
+    ASSERT_TRUE(testCase != NULL);
+    //TODO verify TestCase
+    delete testCase;
+}
+
+TEST_F(ModelBuilderTest, ParsingCaseTest) {
+    android::String8 xmlFile("test_description/host_speaker_calibration.xml");
+    TaskGeneric* testCase = mModelBuilder.parseTestDescriptionXml(xmlFile);
+    ASSERT_TRUE(testCase != NULL);
+    //TODO verify TestCase
+    delete testCase;
+}
+
+TEST_F(ModelBuilderTest, ParsingBatchTest) {
+    android::String8 xmlFile("test_description/all.xml");
+    TaskGeneric* testBatch = mModelBuilder.parseTestDescriptionXml(xmlFile);
+    ASSERT_TRUE(testBatch != NULL);
+    //TODO verify TestCase
+    delete testBatch;
+}
+
+TEST_F(ModelBuilderTest, CaseOnlyTest) {
+    android::String8 xmlFile("test_description/all.xml");
+    TaskGeneric* task = mModelBuilder.parseTestDescriptionXml(xmlFile, true);
+    ASSERT_TRUE(task == NULL);
+
+    delete task;
+}
+
+TEST_F(ModelBuilderTest, MissingMandatoryTest) {
+    android::String8 xmlFile("test_description/test/missing_mandatory.xml");
+    TaskGeneric* task = mModelBuilder.parseTestDescriptionXml(xmlFile);
+    ASSERT_TRUE(task == NULL);
+    delete task;
+}
+
+TEST_F(ModelBuilderTest, UnknownElementTest) {
+    android::String8 xmlFile("test_description/test/unknown_element.xml");
+    TaskGeneric* task = mModelBuilder.parseTestDescriptionXml(xmlFile);
+    ASSERT_TRUE(task == NULL);
+    delete task;
+}
+
+TEST_F(ModelBuilderTest, WrongAttributeTest) {
+    android::String8 xmlFile("test_description/test/wrong_attrib.xml");
+    TaskGeneric* task = mModelBuilder.parseTestDescriptionXml(xmlFile);
+    ASSERT_TRUE(task == NULL);
+    delete task;
+}
+
+TEST_F(ModelBuilderTest, BuiltinRMSTest) {
+    android::String8 xmlFile("test_description/test/test_rms_vma.xml");
+    TaskGeneric* task = mModelBuilder.parseTestDescriptionXml(xmlFile);
+    ASSERT_TRUE(task != NULL);
+    TaskGeneric::ExecutionResult result = task->run();
+    ASSERT_TRUE((result == TaskGeneric::EResultOK) || (result == TaskGeneric::EResultPass));
+    delete task;
+}
+
diff --git a/suite/audio_quality/test/RemoteAudioFakeTcpTest.cpp b/suite/audio_quality/test/RemoteAudioFakeTcpTest.cpp
new file mode 100644
index 0000000..7d77a9b
--- /dev/null
+++ b/suite/audio_quality/test/RemoteAudioFakeTcpTest.cpp
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+// test RemoteAudio with fake TCP
+
+#include <unistd.h>
+
+#include <utils/String8.h>
+
+#include <gtest/gtest.h>
+
+#include <utils/StrongPointer.h>
+
+#include <Log.h>
+#include <audio/AudioHardware.h>
+#include <audio/AudioProtocol.h>
+#include <audio/AudioSignalFactory.h>
+#include <ClientSocket.h>
+#include <audio/RemoteAudio.h>
+
+
+
+void assertTrue(bool cond) {
+    ASSERT_TRUE(cond);
+}
+void assertData(const char* data1, const char* data2, int len) {
+    for (int i = 0; i < len; i++) {
+        //LOGD("0x%x vs 0x%x", data1[i], data2[i]);
+        ASSERT_TRUE(data1[i] == data2[i]);
+    }
+}
+
+class ClientSocketForTest: public ClientSocket {
+public:
+    ClientSocketForTest()
+        : mToRead(NULL),
+          mReadLength(0) {};
+
+    virtual ~ClientSocketForTest() {
+        close(mSocket);
+        close(mPipeWrFd);
+    }
+    virtual bool init(const char* hostIp, int port, bool enableTimeout = false) {
+        LOGD("ClientSocketForTest::init");
+        // use this fd to work with poll
+        int pipefd[2];
+        if (pipe(pipefd)  == -1) {
+            LOGE("cannot create pipe");
+            return false;
+        }
+        LOGD("pipe %d %d", pipefd[0], pipefd[1]);
+        mSocket = pipefd[0];
+        mPipeWrFd = pipefd[1];
+        const char ipExpectation[] = "127.0.0.1";
+        assertTrue(memcmp(ipExpectation, hostIp, sizeof(ipExpectation)) == 0);
+        return true;
+    }
+    virtual bool readData(char* data, int len, int timeoutInMs = 0) {
+        read(mSocket, data, len);
+        return true;
+    }
+    virtual bool sendData(const char* data, int len) {
+        assertTrue((len + mSendPointer) <= mSendLength);
+        assertData(data, mToSend + mSendPointer, len);
+        mSendPointer += len;
+        if ((mToRead != NULL) && (mReadLength != 0)) {
+            LOGD("fake TCP copy reply %d", mReadLength);
+            write(mPipeWrFd, mToRead, mReadLength);
+            mToRead = NULL; // prevent writing the same data again
+        }
+        return true;
+    }
+
+    void setSendExpectation(const char* data, int len) {
+        mToSend = data;
+        mSendLength = len;
+        mSendPointer = 0;
+    }
+    void setReadExpectation(char* data, int len) {
+        mToRead = data;
+        mReadLength = len;
+    }
+public:
+    int mPipeWrFd; // for writing
+    const char* mToRead;
+    int mReadLength;
+    const char* mToSend;
+    int mSendLength;
+    int mSendPointer;
+};
+
+class RemoteAudioFakeTcpTest : public testing::Test {
+protected:
+    android::sp<RemoteAudio> mRemoteAudio;
+    ClientSocketForTest mTestSocket;
+
+protected:
+    virtual void SetUp() {
+        ASSERT_TRUE(U32_ENDIAN_SWAP(0x12345678) == 0x78563412);
+        mRemoteAudio = new RemoteAudio(mTestSocket);
+        ASSERT_TRUE(mRemoteAudio != NULL);
+        ASSERT_TRUE(mRemoteAudio->init(1234));
+    }
+
+    virtual void TearDown() {
+        mRemoteAudio->release();
+        mRemoteAudio.clear();
+    }
+
+    void doDownload() {
+        android::sp<Buffer> buffer = AudioSignalFactory::generateZeroSound(AudioHardware::E2BPS, 2,
+                false);
+        uint32_t prepareSend[] = {
+                U32_ENDIAN_SWAP(AudioProtocol::ECmdDownload),
+                U32_ENDIAN_SWAP(8),
+                U32_ENDIAN_SWAP(0), //id
+                U32_ENDIAN_SWAP(0)
+        };
+        uint32_t prepareReply[] = {
+                U32_ENDIAN_SWAP((AudioProtocol::ECmdDownload & 0xffff) | 0x43210000),
+                0,
+                0
+        };
+        LOGD("reply 0x%x", prepareReply[0]);
+
+        mTestSocket.setSendExpectation((char*)prepareSend, sizeof(prepareSend));
+        // this is reply, but set expectation for reply first as it is sent after send
+        mTestSocket.setReadExpectation((char*)prepareReply, sizeof(prepareReply));
+
+        int id = -1;
+        android::String8 name("1");
+        ASSERT_TRUE(mRemoteAudio->downloadData(name, buffer, id));
+        ASSERT_TRUE(id >= 0);
+    }
+};
+
+TEST_F(RemoteAudioFakeTcpTest, InitTest) {
+    // all done in SetUp
+}
+
+TEST_F(RemoteAudioFakeTcpTest, DownloadTest) {
+    doDownload();
+}
+
+TEST_F(RemoteAudioFakeTcpTest, PlayTest) {
+    doDownload();
+
+    bool stereo = false;
+    int id = 0;
+    int samplingF = 44100;
+    int mode = AudioHardware::EModeVoice | (stereo ? 0x80000000 : 0);
+    int volume = 0;
+    int repeat = 1;
+
+    uint32_t prepareSend[] = {
+            U32_ENDIAN_SWAP(AudioProtocol::ECmdStartPlayback),
+            U32_ENDIAN_SWAP(20),
+            U32_ENDIAN_SWAP(id), //id
+            U32_ENDIAN_SWAP(samplingF),
+            U32_ENDIAN_SWAP(mode),
+            U32_ENDIAN_SWAP(volume),
+            U32_ENDIAN_SWAP(repeat)
+    };
+    uint32_t prepareReply[] = {
+            U32_ENDIAN_SWAP((AudioProtocol::ECmdStartPlayback & 0xffff) | 0x43210000),
+            0,
+            0
+    };
+
+    mTestSocket.setSendExpectation((char*)prepareSend, sizeof(prepareSend));
+    // this is reply, but set expectation for reply first as it is sent after send
+    mTestSocket.setReadExpectation((char*)prepareReply, sizeof(prepareReply));
+
+    ASSERT_TRUE(mRemoteAudio->startPlayback(stereo, samplingF, mode, volume, id, repeat));
+    ASSERT_TRUE(mRemoteAudio->waitForPlaybackCompletion());
+}
+
+TEST_F(RemoteAudioFakeTcpTest, PlayStopTest) {
+    doDownload();
+
+    bool stereo = false;
+    int id = 0;
+    int samplingF = 44100;
+    int mode = AudioHardware::EModeVoice | (stereo ? 0x80000000 : 0);
+    int volume = 0;
+    int repeat = 1;
+
+    uint32_t startPlaybackSend[] = {
+            U32_ENDIAN_SWAP(AudioProtocol::ECmdStartPlayback),
+            U32_ENDIAN_SWAP(20),
+            U32_ENDIAN_SWAP(id),
+            U32_ENDIAN_SWAP(samplingF),
+            U32_ENDIAN_SWAP(mode),
+            U32_ENDIAN_SWAP(volume),
+            U32_ENDIAN_SWAP(repeat)
+    };
+    uint32_t startReply[] = {
+            U32_ENDIAN_SWAP((AudioProtocol::ECmdStartPlayback & 0xffff) | 0x43210000),
+            0,
+            0
+    };
+
+    uint32_t stopPlaybackSend[] = {
+            U32_ENDIAN_SWAP(AudioProtocol::ECmdStopPlayback),
+            U32_ENDIAN_SWAP(0)
+    };
+
+    uint32_t stopReply[] = {
+            U32_ENDIAN_SWAP((AudioProtocol::ECmdStopPlayback & 0xffff) | 0x43210000),
+            0,
+            0
+    };
+
+    mTestSocket.setSendExpectation((char*)startPlaybackSend, sizeof(startPlaybackSend));
+    // this is reply, but set expectation for reply first as it is sent after send
+    mTestSocket.setReadExpectation((char*)startReply, sizeof(startReply));
+
+    ASSERT_TRUE(mRemoteAudio->startPlayback(stereo, samplingF, mode, volume, id, repeat));
+    sleep(1);
+    mTestSocket.setSendExpectation((char*)stopPlaybackSend, sizeof(stopPlaybackSend));
+    // this is reply, but set expectation for reply first as it is sent after send
+    mTestSocket.setReadExpectation((char*)stopReply, sizeof(stopReply));
+    mRemoteAudio->stopPlayback();
+
+    mTestSocket.setSendExpectation((char*)startPlaybackSend, sizeof(startPlaybackSend));
+    // this is reply, but set expectation for reply first as it is sent after send
+    mTestSocket.setReadExpectation((char*)startReply, sizeof(startReply));
+    ASSERT_TRUE(mRemoteAudio->startPlayback(stereo, samplingF, mode, volume, id, repeat));
+    sleep(1);
+    mTestSocket.setSendExpectation((char*)stopPlaybackSend, sizeof(stopPlaybackSend));
+    // this is reply, but set expectation for reply first as it is sent after send
+    mTestSocket.setReadExpectation((char*)stopReply, sizeof(stopReply));
+    mRemoteAudio->stopPlayback();
+
+    mTestSocket.setSendExpectation((char*)startPlaybackSend, sizeof(startPlaybackSend));
+    // this is reply, but set expectation for reply first as it is sent after send
+    mTestSocket.setReadExpectation((char*)startReply, sizeof(startReply));
+    ASSERT_TRUE(mRemoteAudio->startPlayback(stereo, samplingF, mode, volume, id, repeat));
+    ASSERT_TRUE(mRemoteAudio->waitForPlaybackCompletion());
+}
+
+TEST_F(RemoteAudioFakeTcpTest, RecordingTest) {
+    bool stereo = false;
+    int id = 0;
+    int samplingF = 44100;
+    int mode = AudioHardware::EModeVoice | (stereo ? 0x80000000 : 0);
+    int volume = 0;
+    int noSamples = 44; // 1ms worth
+
+    android::sp<Buffer> buffer(new Buffer(100, noSamples*2, false));
+
+    uint32_t startSend[] = {
+            U32_ENDIAN_SWAP(AudioProtocol::ECmdStartRecording),
+            U32_ENDIAN_SWAP(16),
+            U32_ENDIAN_SWAP(samplingF),
+            U32_ENDIAN_SWAP(mode),
+            U32_ENDIAN_SWAP(volume),
+            U32_ENDIAN_SWAP(noSamples)
+    };
+
+    // 2bytes per sample, +2 for last samples rounded off
+    uint32_t startReply[noSamples/2 + 2 + 3];
+    memset(startReply, 0, sizeof(startReply));
+    startReply[0] = U32_ENDIAN_SWAP((AudioProtocol::ECmdStartRecording & 0xffff) | 0x43210000);
+    startReply[1] = 0;
+    startReply[2] = U32_ENDIAN_SWAP(noSamples * 2);
+
+    uint32_t stopSend[] = {
+            U32_ENDIAN_SWAP(AudioProtocol::ECmdStopRecording),
+            U32_ENDIAN_SWAP(0)
+    };
+
+    uint32_t stopReply[] = {
+            U32_ENDIAN_SWAP((AudioProtocol::ECmdStopRecording & 0xffff) | 0x43210000),
+            0,
+            0
+    };
+
+
+    mTestSocket.setSendExpectation((char*)startSend, sizeof(startSend));
+    // this is reply, but set expectation for reply first as it is sent after send
+    mTestSocket.setReadExpectation((char*)startReply, 12 + noSamples*2);
+
+    ASSERT_TRUE(mRemoteAudio->startRecording(stereo, samplingF, mode, volume, buffer));
+    ASSERT_TRUE(mRemoteAudio->waitForRecordingCompletion());
+    ASSERT_TRUE(buffer->amountHandled() == (size_t)(noSamples * 2));
+    mTestSocket.setSendExpectation((char*)startSend, sizeof(startSend));
+    // this is reply, but set expectation for reply first as it is sent after send
+    mTestSocket.setReadExpectation((char*)startReply, 12 + noSamples*2);
+    ASSERT_TRUE(mRemoteAudio->startRecording(stereo, samplingF, mode, volume, buffer));
+    sleep(1);
+    mTestSocket.setSendExpectation((char*)stopSend, sizeof(stopSend));
+    // this is reply, but set expectation for reply first as it is sent after send
+    mTestSocket.setReadExpectation((char*)stopReply, sizeof(stopReply));
+    mRemoteAudio->stopRecording();
+}
diff --git a/suite/audio_quality/test/SignalProcessingInterfaceTest.cpp b/suite/audio_quality/test/SignalProcessingInterfaceTest.cpp
new file mode 100644
index 0000000..cdffeb9
--- /dev/null
+++ b/suite/audio_quality/test/SignalProcessingInterfaceTest.cpp
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#include <gtest/gtest.h>
+#include <utils/String8.h>
+
+#include <audio/AudioSignalFactory.h>
+#include <SignalProcessingInterface.h>
+#include <SignalProcessingImpl.h>
+#include <task/TaskAll.h>
+
+class SignalProcessingInterfaceTest : public testing::Test {
+protected:
+    SignalProcessingImpl* mSp;
+
+protected:
+    virtual void SetUp() {
+        mSp = new SignalProcessingImpl();
+        ASSERT_TRUE(mSp != NULL);
+        ASSERT_TRUE(mSp->init(SignalProcessingImpl::MAIN_PROCESSING_SCRIPT));
+    }
+
+    virtual void TearDown() {
+        delete mSp;
+        mSp = NULL;
+    }
+};
+
+TEST_F(SignalProcessingInterfaceTest, InitTest) {
+    // SetUp do all the work, nothing to do
+}
+
+TEST_F(SignalProcessingInterfaceTest, EchoTest) {
+    android::String8 functionName("echo");
+    int nInputs = 4;
+    int nOutputs = 4;
+    bool inputTypes[4] = { true, true, false, false };
+    bool outputTypes[4] = { true, true, false, false };
+
+    android::sp<Buffer> in0(new Buffer(160000, 160000, true));
+    char* data0 = in0->getData();
+    for (size_t i = 0; i < in0->getSize(); i++) {
+        data0[i] = i;
+    }
+    android::sp<Buffer> in1(new Buffer(8, 8, false));
+    char* data1 = in1->getData();
+    for (size_t i = 0; i < in1->getSize(); i++) {
+        data1[i] = i;
+    }
+    TaskCase::Value in2(1.0f);
+    TaskCase::Value in3((int64_t)100);
+    void* inputs[4] = { &in0, &in1, &in2, &in3 };
+
+    android::sp<Buffer> out0(new Buffer(160000, 160000, true));
+    char* outdata0 = out0->getData();
+    for (size_t i = 0; i < out0->getSize(); i++) {
+        outdata0[i] = 0xaa;
+    }
+    android::sp<Buffer> out1(new Buffer(8, 8, false));
+    char* outdata1 = out1->getData();
+    for (size_t i = 0; i < out1->getSize(); i++) {
+        outdata1[i] = 0xbb;
+    }
+    TaskCase::Value out2(-1.0f);
+    TaskCase::Value out3((int64_t)1000);
+    void *outputs[4] = { &out0, &out1, &out2, &out3 };
+
+    ASSERT_TRUE(mSp->run( functionName,
+            nInputs, inputTypes, inputs,
+            nOutputs, outputTypes, outputs) == TaskGeneric::EResultOK);
+    ASSERT_TRUE(*(in0.get()) == *(out0.get()));
+    ASSERT_TRUE(*(in1.get()) == *(out1.get()));
+    ASSERT_TRUE(in2 == out2);
+    ASSERT_TRUE(in3 == out3);
+}
+
+TEST_F(SignalProcessingInterfaceTest, intsumTest) {
+    android::String8 functionName("intsum");
+    int nInputs = 2;
+    int nOutputs = 1;
+    bool inputTypes[2] = { false, false };
+    bool outputTypes[1] = { false };
+
+    TaskCase::Value in0((int64_t)10);
+    TaskCase::Value in1((int64_t)100);
+    void* inputs[2] = { &in0, &in1 };
+
+    TaskCase::Value out0((int64_t)0);
+    void *outputs[1] = { &out0 };
+
+    ASSERT_TRUE(mSp->run( functionName,
+            nInputs, inputTypes, inputs,
+            nOutputs, outputTypes, outputs) == TaskGeneric::EResultOK);
+    ASSERT_TRUE(out0.getInt64() == (in0.getInt64() + in1.getInt64()));
+}
+
+// two instances of python processing processes should work
+TEST_F(SignalProcessingInterfaceTest, TwoInstanceTest) {
+    SignalProcessingImpl* sp2 = new SignalProcessingImpl();
+    ASSERT_TRUE(sp2 != NULL);
+    ASSERT_TRUE(sp2->init(SignalProcessingImpl::MAIN_PROCESSING_SCRIPT));
+
+    android::String8 functionName("intsum");
+    int nInputs = 2;
+    int nOutputs = 1;
+    bool inputTypes[2] = { false, false };
+    bool outputTypes[1] = { false };
+
+    TaskCase::Value in0((int64_t)10);
+    TaskCase::Value in1((int64_t)100);
+    void* inputs[2] = { &in0, &in1 };
+
+    TaskCase::Value out0((int64_t)0);
+    void *outputs[1] = { &out0 };
+
+    ASSERT_TRUE(mSp->run( functionName,
+            nInputs, inputTypes, inputs,
+            nOutputs, outputTypes, outputs) == TaskGeneric::EResultOK);
+    ASSERT_TRUE(out0.getInt64() == (in0.getInt64() + in1.getInt64()));
+    out0.setInt64(0);
+    ASSERT_TRUE(sp2->run( functionName,
+                nInputs, inputTypes, inputs,
+                nOutputs, outputTypes, outputs) == TaskGeneric::EResultOK);
+    ASSERT_TRUE(out0.getInt64() == (in0.getInt64() + in1.getInt64()));
+    delete sp2;
+}
+
+// test to run processing/example.py
+TEST_F(SignalProcessingInterfaceTest, exampleTest) {
+    android::String8 functionName("example");
+    int nInputs = 8;
+    int nOutputs = 4;
+    bool inputTypes[8] = { true, true, true, true, false, false, false, false };
+    bool outputTypes[4] = { true, true, false, false };
+
+    android::sp<Buffer> in0(new Buffer(16, 16, true));
+    char* data0 = in0->getData();
+    for (size_t i = 0; i < in0->getSize(); i++) {
+        data0[i] = i;
+    }
+    android::sp<Buffer> in1(new Buffer(16, 16, true));
+    char* data1 = in1->getData();
+    for (size_t i = 0; i < in1->getSize(); i++) {
+        data1[i] = i;
+    }
+    android::sp<Buffer> in2(new Buffer(8, 8, false));
+    char* data2 = in2->getData();
+    for (size_t i = 0; i < in2->getSize(); i++) {
+        data2[i] = i;
+    }
+    android::sp<Buffer> in3(new Buffer(8, 8, false));
+    char* data3 = in3->getData();
+    for (size_t i = 0; i < in3->getSize(); i++) {
+        data3[i] = i;
+    }
+    TaskCase::Value in4((int64_t)100);
+    TaskCase::Value in5((int64_t)100);
+    TaskCase::Value in6(1.0f);
+    TaskCase::Value in7(1.0f);
+    void* inputs[8] = { &in0, &in1, &in2, &in3, &in4, &in5, &in6, &in7 };
+
+    android::sp<Buffer> out0(new Buffer(16, 16, true));
+    char* outdata0 = out0->getData();
+    for (size_t i = 0; i < out0->getSize(); i++) {
+        outdata0[i] = 0xaa;
+    }
+    android::sp<Buffer> out1(new Buffer(8, 8, false));
+    char* outdata1 = out1->getData();
+    for (size_t i = 0; i < out1->getSize(); i++) {
+        outdata1[i] = 0xbb;
+    }
+    TaskCase::Value out2((int64_t)1000);
+    TaskCase::Value out3(-1.0f);
+    void *outputs[4] = { &out0, &out1, &out2, &out3 };
+
+    ASSERT_TRUE(mSp->run( functionName,
+            nInputs, inputTypes, inputs,
+            nOutputs, outputTypes, outputs) == TaskGeneric::EResultOK);
+    ASSERT_TRUE(*(in0.get()) == *(out0.get()));
+    ASSERT_TRUE(*(in2.get()) == *(out1.get()));
+    ASSERT_TRUE(in4 == out2);
+    ASSERT_TRUE(in6 == out3);
+}
diff --git a/suite/audio_quality/test/SimpleScriptExecTest.cpp b/suite/audio_quality/test/SimpleScriptExecTest.cpp
new file mode 100644
index 0000000..7016ef9
--- /dev/null
+++ b/suite/audio_quality/test/SimpleScriptExecTest.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+
+#include <gtest/gtest.h>
+#include <SimpleScriptExec.h>
+
+
+class ScriptExecTest : public testing::Test {
+
+};
+
+TEST_F(ScriptExecTest, PythonVersionTest) {
+    ASSERT_TRUE(SimpleScriptExec::checkPythonEnv());
+}
+
+
+TEST_F(ScriptExecTest, checkIfPassedTest) {
+    android::String8 pass1("___CTS_AUDIO_PASS___");
+    android::String8 match1;
+    ASSERT_TRUE(SimpleScriptExec::checkIfPassed(pass1, match1));
+
+    android::String8 fail1;
+    ASSERT_TRUE(!SimpleScriptExec::checkIfPassed(fail1, match1));
+}
+
diff --git a/suite/audio_quality/test/StringUtilTest.cpp b/suite/audio_quality/test/StringUtilTest.cpp
new file mode 100644
index 0000000..1dbcea0
--- /dev/null
+++ b/suite/audio_quality/test/StringUtilTest.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#include <gtest/gtest.h>
+#include <StringUtil.h>
+
+
+class StringUtilTest : public testing::Test {
+
+};
+
+TEST_F(StringUtilTest, compareTest) {
+    android::String8 str("hello");
+    ASSERT_TRUE(StringUtil::compare(str, "hello") == 0);
+    ASSERT_TRUE(StringUtil::compare(str, "hi") != 0);
+}
+
+TEST_F(StringUtilTest, substrTest) {
+    android::String8 str("hello there");
+
+    android::String8 sub1 = StringUtil::substr(str, 0, 5);
+    ASSERT_TRUE(StringUtil::compare(sub1, "hello") == 0);
+
+    android::String8 sub2 = StringUtil::substr(str, 10, 5);
+    ASSERT_TRUE(StringUtil::compare(sub2, "e") == 0);
+
+    android::String8 sub3 = StringUtil::substr(str, 6, 5);
+    ASSERT_TRUE(StringUtil::compare(sub3, "there") == 0);
+
+    android::String8 sub4 = StringUtil::substr(str, 100, 5);
+    ASSERT_TRUE(sub4.length() == 0);
+}
+
+TEST_F(StringUtilTest, endsWithTest) {
+    android::String8 str("hello there");
+    ASSERT_TRUE(StringUtil::endsWith(str, "there"));
+    ASSERT_TRUE(StringUtil::endsWith(str, "hello there"));
+    ASSERT_TRUE(!StringUtil::endsWith(str, "not there"));
+}
+
+TEST_F(StringUtilTest, splitTest) {
+    android::String8 str("hello:there:break:this:");
+    std::vector<android::String8>* tokens = StringUtil::split(str, ':');
+    ASSERT_TRUE(tokens != NULL);
+    ASSERT_TRUE(tokens->size() == 4);
+    ASSERT_TRUE(StringUtil::compare(tokens->at(0), "hello") == 0);
+    ASSERT_TRUE(StringUtil::compare(tokens->at(1), "there") == 0);
+    ASSERT_TRUE(StringUtil::compare(tokens->at(2), "break") == 0);
+    ASSERT_TRUE(StringUtil::compare(tokens->at(3), "this") == 0);
+    delete tokens;
+
+    android::String8 str2("::::");
+    std::vector<android::String8>* tokens2 = StringUtil::split(str2, ':');
+    ASSERT_TRUE(tokens2 != NULL);
+    ASSERT_TRUE(tokens2->size() == 0);
+    delete tokens2;
+}
+
+
+
diff --git a/suite/audio_quality/test/TaskCaseCommon.h b/suite/audio_quality/test/TaskCaseCommon.h
new file mode 100644
index 0000000..cf8d272
--- /dev/null
+++ b/suite/audio_quality/test/TaskCaseCommon.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+
+#ifndef CTSAUDIO_TASKCASECOMMON_H
+#define CTSAUDIO_TASKCASECOMMON_H
+
+#include <gtest/gtest.h>
+
+#include <Log.h>
+#include <GenericFactory.h>
+#include <task/TaskAll.h>
+
+/**
+ * Create TaskCase with setup and action as children
+ * No need to destroy setup and action
+ */
+inline TaskCase* getTaskCase(TaskGeneric*& setup, TaskGeneric*& action)
+{
+    GenericFactory factory;
+    TaskCase* taskCase = new TaskCase();
+    setup = factory.createTask(TaskGeneric::ETaskSetup);
+    taskCase->addChild(setup);
+    action = factory.createTask(TaskGeneric::ETaskAction);
+    taskCase->addChild(action);
+    return taskCase;
+}
+
+
+#endif // CTSAUDIO_TASKCASECOMMON_H
diff --git a/suite/audio_quality/test/TaskCaseTest.cpp b/suite/audio_quality/test/TaskCaseTest.cpp
new file mode 100644
index 0000000..9cf74a7
--- /dev/null
+++ b/suite/audio_quality/test/TaskCaseTest.cpp
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#include <stdint.h>
+#include <gtest/gtest.h>
+
+#include "Log.h"
+#include "StringUtil.h"
+#include "task/TaskAll.h"
+
+
+class TaskCaseTest : public testing::Test {
+public:
+    TaskCase* mTaskCase;
+    virtual void SetUp() {
+        mTaskCase = new TaskCase();
+        ASSERT_TRUE(mTaskCase != NULL);
+    }
+
+    virtual void TearDown() {
+        delete mTaskCase;
+    }
+};
+
+
+TEST_F(TaskCaseTest, DataMapTest) {
+    android::sp<Buffer> buffer1(new Buffer(4, 4, true));
+    android::sp<Buffer> buffer2(new Buffer(4, 4, true));
+    android::sp<Buffer> buffer3(new Buffer(4, 4, true));
+    android::sp<Buffer> buffer4(new Buffer(4, 4, true));
+
+    const android::String8 BUFFER1("buffer1");
+    const android::String8 BUFFER2("buffer2");
+    const android::String8 BUFFER3("buffer3");
+    const android::String8 BUFFER4("buffer4");
+    ASSERT_TRUE(mTaskCase->registerBuffer(BUFFER1, buffer1));
+    ASSERT_TRUE(mTaskCase->registerBuffer(BUFFER2, buffer2));
+    ASSERT_TRUE(mTaskCase->registerBuffer(BUFFER3, buffer3));
+    ASSERT_TRUE(mTaskCase->registerBuffer(BUFFER4, buffer4));
+
+    android::sp<Buffer> buffer1f = mTaskCase->findBuffer(BUFFER1);
+    //LOGI("buffer1 %x, buffer1f %x", &buffer1, buffer1f);
+    ASSERT_TRUE(buffer1.get() == buffer1f.get());
+    const android::String8 NO_SUCH_BUFFER("no_such_buffer");
+    buffer1f = mTaskCase->findBuffer(NO_SUCH_BUFFER);
+    ASSERT_TRUE(buffer1f.get() == NULL);
+    const android::String8 RE("buffer[1-2]");
+    std::list<TaskCase::BufferPair>* list = mTaskCase->findAllBuffers(RE);
+    ASSERT_TRUE(list != NULL);
+    ASSERT_TRUE(((list->front().second.get() == buffer1.get()) &&
+                    (list->back().second.get() == buffer2.get())) ||
+                ((list->front().second.get() == buffer2.get()) &&
+                    (list->back().second.get() == buffer1.get())));
+    delete list;
+}
+
+TEST_F(TaskCaseTest, ValueMapTest) {
+    TaskCase::Value val1(1.0f);
+    TaskCase::Value val2(2.0f);
+    TaskCase::Value val3((int64_t)1);
+    TaskCase::Value val4((int64_t)2);
+    TaskCase::Value val2_copy(2.0f);
+    ASSERT_TRUE(!(val1 == val2));
+    ASSERT_TRUE(!(val2 == val3));
+    ASSERT_TRUE(val2 == val2_copy);
+    ASSERT_TRUE(val1.getDouble() == 1.0f);
+    ASSERT_TRUE(val3.getInt64() == 1);
+    const android::String8 V1("v1");
+    const android::String8 V2("v2");
+    const android::String8 V3("v3");
+    const android::String8 V4("v4");
+    const android::String8 V5("v5");
+    ASSERT_TRUE(mTaskCase->registerValue(V1, val1));
+    ASSERT_TRUE(mTaskCase->registerValue(V2, val2));
+    ASSERT_TRUE(mTaskCase->registerValue(V3, val3));
+    ASSERT_TRUE(mTaskCase->registerValue(V4, val4));
+
+    TaskCase::Value valRead;
+    ASSERT_TRUE(mTaskCase->findValue(V4, valRead));
+    ASSERT_TRUE(valRead.getInt64() == 2);
+    TaskCase::Value val4_2((int64_t)3);
+    ASSERT_TRUE(mTaskCase->updateValue(V4, val4_2));
+    ASSERT_TRUE(mTaskCase->findValue(V4, valRead));
+    ASSERT_TRUE(valRead.getInt64() == 3);
+    ASSERT_TRUE(!mTaskCase->updateValue(V5, val4));
+    ASSERT_TRUE(!mTaskCase->findValue(V5, valRead));
+
+    const android::String8 RE("v[2-3]");
+    std::list<TaskCase::ValuePair>* list = mTaskCase->findAllValues(RE);
+    ASSERT_TRUE(list != NULL);
+    ASSERT_TRUE(((list->front().second == val2) && (list->back().second == val3)) ||
+                ((list->front().second == val3) && (list->back().second == val4)));
+    delete list;
+}
+
+TEST_F(TaskCaseTest, IndexMapTest) {
+    Buffer buffer1(4, 4, true);
+    Buffer buffer2(4, 4, true);
+    Buffer buffer3(4, 4, true);
+    Buffer buffer4(4, 4, true);
+
+    int i = 0;
+    int j = 1;
+    const android::String8 I("i");
+    const android::String8 J("j");
+    const android::String8 K("k");
+    ASSERT_TRUE(mTaskCase->registerIndex(I));
+    ASSERT_TRUE(mTaskCase->registerIndex(J));
+    ASSERT_TRUE(mTaskCase->updateIndex(I, i));
+    ASSERT_TRUE(mTaskCase->updateIndex(J, j));
+    int i_read, j_read, k_read;
+    ASSERT_TRUE(mTaskCase->findIndex(I, i_read));
+    ASSERT_TRUE(mTaskCase->findIndex(J, j_read));
+    ASSERT_TRUE(!mTaskCase->findIndex(K, k_read));
+    ASSERT_TRUE(i == i_read);
+    ASSERT_TRUE(j == j_read);
+    //TODO add findAll test
+}
+
+TEST_F(TaskCaseTest, VarTranslateTest) {
+    const android::String8 I("i");
+    const android::String8 J("j");
+    const android::String8 K("k");
+    ASSERT_TRUE(mTaskCase->registerIndex(I, 1));
+    ASSERT_TRUE(mTaskCase->registerIndex(J, 2));
+    ASSERT_TRUE(mTaskCase->registerIndex(K, 3));
+
+    android::String8 orig1("hello_$i_$j");
+    android::String8 result1;
+    ASSERT_TRUE(mTaskCase->translateVarName(orig1, result1));
+    ASSERT_TRUE(StringUtil::compare(result1, "hello_1_2") == 0);
+
+    android::String8 orig2("hello_$i_$j_$k_there");
+    android::String8 result2;
+    ASSERT_TRUE(mTaskCase->translateVarName(orig2, result2));
+    ASSERT_TRUE(StringUtil::compare(result2, "hello_1_2_3_there") == 0);
+
+    // should fail as there is no such var
+    android::String8 orig3("$n");
+    android::String8 result3;
+    ASSERT_TRUE(!mTaskCase->translateVarName(orig3, result3));
+
+    android::String8 orig4("hello_there");
+    android::String8 result4;
+    ASSERT_TRUE(mTaskCase->translateVarName(orig4, result4));
+    ASSERT_TRUE(StringUtil::compare(result4, "hello_there") == 0);
+}
diff --git a/suite/audio_quality/test/TaskProcessTest.cpp b/suite/audio_quality/test/TaskProcessTest.cpp
new file mode 100644
index 0000000..05c7f1d
--- /dev/null
+++ b/suite/audio_quality/test/TaskProcessTest.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+
+#include "TaskCaseCommon.h"
+
+class TaskProcessTest : public testing::Test {
+public:
+    TaskCase* mTestCase;
+    TaskSequential* mSequential;
+    TaskProcess* mProcess;
+
+
+    virtual void SetUp() {
+        TaskGeneric* setup = NULL;
+        TaskGeneric* action = NULL;
+        mTestCase  = getTaskCase(setup, action);
+        ASSERT_TRUE(mTestCase != NULL);
+        ASSERT_TRUE(setup != NULL);
+        ASSERT_TRUE(action != NULL);
+        mSequential = new TaskSequential();
+        const android::String8 REPEAT("repeat");
+        const android::String8 N_10("10");
+        const android::String8 INDEX("index");
+        const android::String8 I("i");
+        ASSERT_TRUE(mSequential->parseAttribute(REPEAT, N_10));
+        ASSERT_TRUE(mSequential->parseAttribute(INDEX, I));
+        ASSERT_TRUE(action->addChild(mSequential));
+        mProcess = new TaskProcess();
+        ASSERT_TRUE(mSequential->addChild(mProcess));
+
+    }
+
+    virtual void TearDown() {
+        delete mTestCase;
+    }
+};
+
+
+TEST_F(TaskProcessTest, AttributeTest) {
+
+}
+
+
diff --git a/suite/audio_quality/test/TaskSequentialTest.cpp b/suite/audio_quality/test/TaskSequentialTest.cpp
new file mode 100644
index 0000000..289dafe
--- /dev/null
+++ b/suite/audio_quality/test/TaskSequentialTest.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#include "TaskCaseCommon.h"
+class TaskSequentialTest : public testing::Test {
+public:
+    TaskCase* mTestCase;
+    TaskSequential* mSequential;
+
+
+    virtual void SetUp() {
+        TaskGeneric* setup = NULL;
+        TaskGeneric* action = NULL;
+        mTestCase  = getTaskCase(setup, action);
+        ASSERT_TRUE(mTestCase != NULL);
+        ASSERT_TRUE(setup != NULL);
+        ASSERT_TRUE(action != NULL);
+        mSequential = new TaskSequential();
+        action->addChild(mSequential);
+    }
+
+    virtual void TearDown() {
+        delete mTestCase;
+    }
+};
+
+
+TEST_F(TaskSequentialTest, AttributeTest) {
+    const android::String8 REPEAT("repeat");
+    const android::String8 N_10("10");
+    const android::String8 INDEX("index");
+    const android::String8 I("i");
+    const android::String8 NO_SUCH_THING("no_such_thing");
+    const android::String8 SHOULD_FAIL("should_fail");
+    ASSERT_TRUE(mSequential->parseAttribute(REPEAT, N_10));
+    ASSERT_TRUE(mSequential->parseAttribute(INDEX, I));
+    ASSERT_TRUE(!mSequential->parseAttribute(NO_SUCH_THING, SHOULD_FAIL));
+    mSequential->run();
+    const android::String8 RE(".*");
+    std::list<TaskCase::IndexPair>* indices = mTestCase->findAllIndices(RE);
+    ASSERT_TRUE(indices != NULL);
+    ASSERT_TRUE(indices->size() == 1);
+    int index = -10;
+
+    ASSERT_TRUE(mTestCase->findIndex(I, index));
+    ASSERT_TRUE(index == 10);
+    delete indices;
+}
+
+
+
+
diff --git a/suite/audio_quality/test/TaskTest.cpp b/suite/audio_quality/test/TaskTest.cpp
new file mode 100644
index 0000000..b003d99
--- /dev/null
+++ b/suite/audio_quality/test/TaskTest.cpp
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#include <gtest/gtest.h>
+#include "task/TaskAll.h"
+
+static const android::String8 AAA("aaa");
+static const android::String8 BBB("bbb");
+
+class TaskTest : public testing::Test {
+public:
+    TaskCase* mTestCase;
+    // should not delete
+    TaskGeneric* mTaskSetup;
+    TaskGeneric* mTaskAction;
+    TaskGeneric* mTaskSequential;
+    TaskGeneric* mTaskProcess;
+    TaskGeneric* mTaskInput;
+    TaskGeneric* mTaskOutput;
+    TaskGeneric* mTaskSound;
+
+    class TestTaskDummy: public TaskGeneric {
+    public:
+        static int mRunCounter;
+        static int mLiveInstanceCounter;
+
+        TestTaskDummy(TaskGeneric::TaskType type)
+            : TaskGeneric(type) {
+            mLiveInstanceCounter++;
+
+
+            const android::String8* list[] = {&AAA, &BBB, NULL};
+            registerSupportedStringAttributes(list);
+        };
+        virtual ~TestTaskDummy(){
+            mLiveInstanceCounter--;
+        };
+
+        virtual TaskGeneric::ExecutionResult run()
+        {
+            mRunCounter++;
+            return TaskGeneric::run();
+        };
+        bool addStringAttributePublic(const android::String8& key, android::String8& value){
+            return addStringAttribute(key, value);
+        }
+        bool findStringAttributePublic(const android::String8& key, android::String8& value){
+            return findStringAttribute(key, value);
+        }
+    };
+
+    virtual void SetUp() {
+        TestTaskDummy::mRunCounter = 0;
+        TestTaskDummy::mLiveInstanceCounter = 0;
+        mTestCase = new TaskCase();
+        mTaskSetup = new TestTaskDummy(TaskGeneric::ETaskSetup);
+        mTaskAction = new TestTaskDummy(TaskGeneric::ETaskAction);
+        ASSERT_TRUE(mTestCase->addChild(mTaskSetup));
+        ASSERT_TRUE(mTestCase->addChild(mTaskAction));
+        mTaskSequential = new TestTaskDummy(TaskGeneric::ETaskSequential);
+        ASSERT_TRUE(mTaskAction->addChild(mTaskSequential));
+        mTaskProcess = new TestTaskDummy(TaskGeneric::ETaskProcess);
+        mTaskInput = new TestTaskDummy(TaskGeneric::ETaskInput);
+        mTaskOutput = new TestTaskDummy(TaskGeneric::ETaskOutput);
+        ASSERT_TRUE(mTaskSequential->addChild(mTaskOutput));
+        ASSERT_TRUE(mTaskSequential->addChild(mTaskInput));
+        ASSERT_TRUE(mTaskSequential->addChild(mTaskProcess));
+        mTaskSound = new TestTaskDummy(TaskGeneric::ETaskSound);
+        ASSERT_TRUE(mTaskSetup->addChild(mTaskSound));
+        ASSERT_TRUE(TestTaskDummy::mLiveInstanceCounter == 7);
+    }
+
+    virtual void TearDown() {
+        if(mTestCase != NULL) {
+            delete mTestCase;
+        }
+        ASSERT_TRUE(TestTaskDummy::mLiveInstanceCounter == 0);
+    }
+};
+
+int TaskTest::TestTaskDummy::mRunCounter = 0;
+int TaskTest::TestTaskDummy::mLiveInstanceCounter = 0;
+
+TEST_F(TaskTest, HierarchyTest) {
+    // verify hierarchy
+    ASSERT_TRUE(mTaskSetup->getTestCase() == mTestCase);
+    ASSERT_TRUE(mTaskAction->getTestCase() == mTestCase);
+    ASSERT_TRUE(mTaskSequential->getTestCase() == mTestCase);
+    ASSERT_TRUE(mTaskProcess->getTestCase() == mTestCase);
+    ASSERT_TRUE(mTaskInput->getTestCase() == mTestCase);
+    ASSERT_TRUE(mTaskOutput->getTestCase() == mTestCase);
+    ASSERT_TRUE(mTaskSound->getTestCase() == mTestCase);
+}
+
+TEST_F(TaskTest, RunTest) {
+    ASSERT_TRUE(mTestCase->run() == TaskGeneric::EResultOK);
+    ASSERT_TRUE(TestTaskDummy::mRunCounter == 7);
+}
+
+TEST_F(TaskTest, StringAttributeTest) {
+    android::String8 aaaVal("aaa_val");
+    android::String8 bbbVal("bbb_val");
+    android::String8 read;
+    TestTaskDummy* task = reinterpret_cast<TestTaskDummy*>(mTaskSetup);
+    ASSERT_TRUE(task->addStringAttributePublic(AAA, aaaVal));
+    ASSERT_TRUE(task->addStringAttributePublic(BBB, bbbVal));
+    const android::String8 CCC("ccc");
+    ASSERT_TRUE(!task->addStringAttributePublic(CCC, bbbVal));
+    ASSERT_TRUE(task->findStringAttributePublic(AAA, read));
+    ASSERT_TRUE(read == aaaVal);
+    ASSERT_TRUE(task->findStringAttributePublic(BBB, read));
+    ASSERT_TRUE(read == bbbVal);
+    const android::String8 VERSION("version");
+    const android::String8 NAME("name");
+    ASSERT_TRUE(!task->findStringAttributePublic(VERSION, read));
+    ASSERT_TRUE(!task->findStringAttributePublic(NAME, read));
+}
+
+