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.
Change-Id: I5288dec42f272260f30f1ace1374d365e31d1664
diff --git a/suite/audio_quality/lib/include/audio/AudioHardware.h b/suite/audio_quality/lib/include/audio/AudioHardware.h
new file mode 100644
index 0000000..c505c31
--- /dev/null
+++ b/suite/audio_quality/lib/include/audio/AudioHardware.h
@@ -0,0 +1,95 @@
+/*
+ * 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_AUDIOHARDWARE_H
+#define CTSAUDIO_AUDIOHARDWARE_H
+
+#include <utils/StrongPointer.h>
+#include <utils/RefBase.h>
+#include "Buffer.h"
+
+class TaskCase;
+/**
+ * Utility class for H/W detection
+ */
+class AudioHardware : virtual public android::RefBase {
+public:
+ /** audio length should be multiple of this */
+ static const int SAMPLES_PER_ONE_GO = 4096;
+
+ enum SamplingRate {
+ ESamplingRateInvald = 0,
+ ESampleRate_16000 = 16000,
+ ESampleRate_44100 = 44100
+ };
+ enum BytesPerSample {
+ E2BPS = 2
+ };
+ enum AudioMode {
+ EModeVoice = 0,
+ EModeMusic = 1
+ };
+
+ /**
+ * detect supported audio H/W
+ * @return card number of detected H/W. -1 if not found.
+ */
+ static int detectAudioHw();
+
+ /**
+ * Factory method
+ * options are : local or remote, playback or recording
+ * can return NULL(sp.get() == NULL) if H/W not found
+ */
+ static android::sp<AudioHardware> createAudioHw(bool local, bool playback,
+ TaskCase* testCase = NULL);
+
+ virtual ~AudioHardware();
+ /**
+ * prepare playback or recording
+ */
+ virtual bool prepare(SamplingRate samplingRate, int volume, int mode = EModeVoice) = 0;
+
+ /**
+ * Convenience API to pass buffer ID. The buffer can be either present in testCase
+ * or in remote device (when testCase is NULL)
+ */
+ virtual bool startPlaybackOrRecordById(const android::String8& id, TaskCase* testCase = NULL);
+
+ /**
+ * Playback / Record with given buffer
+ * @param buffer buffer to play / record
+ * @param numberRepetition How many times to repeat playback / record for given buffer.
+ * For record, it does not have much meaning as the last recording will always
+ * override.
+ */
+ virtual bool startPlaybackOrRecord(android::sp<Buffer>& buffer,
+ int numberRepetition = 1) = 0;
+ /**
+ * Wait for the playback / recording to complete. return true when successfully finished.
+ * Calling waitForCompletion after calling stopPlaybackOrRecord will lead into blocking
+ * the calling thread for some time.
+ */
+ virtual bool waitForCompletion() = 0;
+ /// stops the on-going action. The active task can be canceled.
+ virtual void stopPlaybackOrRecord() = 0;
+
+protected:
+ static int mHwId;
+};
+
+
+#endif // CTSAUDIO_AUDIOHARDWARE_H
diff --git a/suite/audio_quality/lib/include/audio/AudioLocal.h b/suite/audio_quality/lib/include/audio/AudioLocal.h
new file mode 100644
index 0000000..a263528
--- /dev/null
+++ b/suite/audio_quality/lib/include/audio/AudioLocal.h
@@ -0,0 +1,97 @@
+/*
+ * 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_AUDIOLOCAL_H
+#define CTSAUDIO_AUDIOLOCAL_H
+
+#include <utils/StrongPointer.h>
+#include <utils/threads.h>
+
+#include <Semaphore.h>
+
+#include "AudioHardware.h"
+
+class Buffer;
+
+/**
+ * Basic API for playback and record
+ */
+class AudioLocal: public android::Thread, public AudioHardware {
+public:
+
+ virtual bool prepare(AudioHardware::SamplingRate samplingRate, int gain,
+ int mode = AudioHardware::EModeVoice);
+ virtual bool startPlaybackOrRecord(android::sp<Buffer>& buffer, int numberRepetition = 1);
+ virtual bool waitForCompletion();
+ virtual void stopPlaybackOrRecord();
+
+ virtual ~AudioLocal();
+protected:
+ AudioLocal();
+
+ virtual bool doPrepare(AudioHardware::SamplingRate, int samplesInOneGo) = 0;
+ virtual bool doPlaybackOrRecord(android::sp<Buffer>& buffer) = 0;
+ virtual void doStop() = 0;
+ virtual void releaseHw() {};
+
+private:
+
+
+ bool threadLoop();
+
+ enum AudioCommand{
+ ECmNone = 0,
+ ECmInitialize,
+ ECmRun,
+ ECmStop,
+ ECmThreadStop // terminate the thread
+ };
+
+ bool issueCommandAndWaitForCompletion(AudioCommand command);
+
+protected:
+
+private:
+ // only one command at a time.
+ // Thus, all parameters can be stored here.
+ AudioHardware::SamplingRate mSamplingRate;
+
+ android::sp<Buffer> mBuffer;
+ int mNumberRepetition;
+ int mCurrentRepeat;
+
+ enum AudioState{
+ EStNone,
+ EStCreated,
+ EStInitialized,
+ EStRunning // playing or recording
+ };
+ volatile AudioState mState;
+ volatile AudioCommand mCurrentCommand;
+
+
+ static const int COMMAND_WAIT_TIME_MSEC = 4000;
+
+ Semaphore mClientCommandWait;
+ Semaphore mClientCompletionWait;
+ Semaphore mAudioThreadWait;
+
+ bool mCommandResult;
+ bool mCompletionResult;
+};
+
+#endif // CTSAUDIO_AUDIOLOCAL_H
diff --git a/suite/audio_quality/lib/include/audio/AudioPlaybackLocal.h b/suite/audio_quality/lib/include/audio/AudioPlaybackLocal.h
new file mode 100644
index 0000000..94422af
--- /dev/null
+++ b/suite/audio_quality/lib/include/audio/AudioPlaybackLocal.h
@@ -0,0 +1,48 @@
+/*
+ * 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_AUDIOPLAYBACKLOCAL_H
+#define CTSAUDIO_AUDIOPLAYBACKLOCAL_H
+
+#include <utils/String8.h>
+
+#include <tinyalsa/asoundlib.h>
+
+#include "AudioLocal.h"
+
+
+class AudioPlaybackLocal: public AudioLocal {
+public:
+ AudioPlaybackLocal(int hwId);
+ virtual ~AudioPlaybackLocal();
+protected:
+ bool doPrepare(AudioHardware::SamplingRate, int samplesInOneGo);
+ bool doPlaybackOrRecord(android::sp<Buffer>& buffer);
+ void doStop();
+ void releaseHw();
+
+private:
+ int mHwId;
+ struct pcm* mPcmHandle;
+ // unit playback samples
+ int mSamples;
+ // unit playback sizes
+ int mSizes;
+};
+
+
+#endif // CTSAUDIO_AUDIOPLAYBACKLOCAL_H
diff --git a/suite/audio_quality/lib/include/audio/AudioProtocol.h b/suite/audio_quality/lib/include/audio/AudioProtocol.h
new file mode 100644
index 0000000..83ba922
--- /dev/null
+++ b/suite/audio_quality/lib/include/audio/AudioProtocol.h
@@ -0,0 +1,146 @@
+/*
+ * 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_AUDIOPROTOCOL_H
+#define CTSAUDIO_AUDIOPROTOCOL_H
+
+#include <stdint.h>
+
+#include <utils/StrongPointer.h>
+#include "Log.h"
+#include "audio/Buffer.h"
+#include "ClientSocket.h"
+
+#define U32_ENDIAN_SWAP(x) ( ((x) & 0x000000ff)<<24 | ((x) & 0x0000ff00)<<8 | \
+ ((x) & 0x00ff0000)>>8 | ((x) & 0xff000000)>>24 )
+
+class AudioParam {
+public:
+ bool mStereo;
+ uint32_t mSamplingF;
+ uint32_t mMode;
+ uint32_t mNumberRepetition; // only for playback
+ uint32_t mVolume;
+ uint32_t mId;
+ android::sp<Buffer> mBuffer;
+};
+
+class AudioProtocol {
+public:
+ enum CommandId {
+ ECmdStart = 0x12340001, //not actual command
+ ECmdDownload = 0x12340001,
+ ECmdStartPlayback = 0x12340002,
+ ECmdStopPlayback = 0x12340003,
+ ECmdStartRecording = 0x12340004,
+ ECmdStopRecording = 0x12340005,
+ ECmdLast = 0x12340006, // not actual command
+ };
+
+ static const uint32_t REPLY_HEADER_SIZE = 12;
+ // up to 5 parameters for command / reply
+ class ProtocolParam {
+ public:
+ void* param[5];
+ };
+
+ virtual ~AudioProtocol() {
+ //LOGD("~AudioProtocol %x", this);
+ };
+
+ /// default implementation, no param, no payload
+ virtual bool sendCommand(AudioParam& param);
+ /// default implementation, no param, no payload
+ virtual bool handleReply(const uint32_t* data, AudioParam* param);
+
+ /**
+ * read header of reply and returns CommandId of reply.
+ * @param socket socket to read
+ * @param data pointer to buffer to store header, it should be uint32_t[3]
+ * @param id types of reply
+ * @return true if everything OK
+ */
+ static bool handleReplyHeader(ClientSocket& socket, uint32_t* data, CommandId& id);
+
+protected:
+ AudioProtocol(ClientSocket& socket, uint32_t command)
+ : mCommand(command),
+ mSocket(socket) {};
+
+ bool sendData(const char* data, int len) {
+ return mSocket.sendData(data, len);
+ };
+
+ bool checkHeaderId(const uint32_t* data, uint32_t command);
+ bool readData(char* data, int len) {
+ return mSocket.readData(data, len);
+ };
+
+protected:
+ int mBuffer[8];
+private:
+ uint32_t mCommand;
+ ClientSocket& mSocket;
+
+};
+
+class CmdDownload: public AudioProtocol {
+public:
+ CmdDownload(ClientSocket& socket)
+ : AudioProtocol(socket, ECmdDownload) {};
+ virtual ~CmdDownload() {};
+ virtual bool sendCommand(AudioParam& param);
+};
+
+
+class CmdStartPlayback: public AudioProtocol {
+public:
+ CmdStartPlayback(ClientSocket& socket)
+ : AudioProtocol(socket, ECmdStartPlayback) {};
+ virtual ~CmdStartPlayback() {};
+ virtual bool sendCommand(AudioParam& param);
+};
+
+class CmdStopPlayback: public AudioProtocol {
+public:
+ CmdStopPlayback(ClientSocket& socket)
+ : AudioProtocol(socket, ECmdStopPlayback) {};
+ virtual ~CmdStopPlayback() {};
+};
+
+class CmdStartRecording: public AudioProtocol {
+public:
+ CmdStartRecording(ClientSocket& socket)
+ : AudioProtocol(socket, ECmdStartRecording) {};
+ virtual ~CmdStartRecording() {};
+
+ virtual bool sendCommand(AudioParam& param);
+
+ virtual bool handleReply(const uint32_t* data, AudioParam* param);
+};
+
+class CmdStopRecording: public AudioProtocol {
+public:
+ CmdStopRecording(ClientSocket& socket)
+ : AudioProtocol(socket, ECmdStopRecording) {};
+ virtual ~CmdStopRecording() {};
+};
+
+
+
+
+#endif // CTSAUDIO_AUDIOPROTOCOL_H
diff --git a/suite/audio_quality/lib/include/audio/AudioRecordingLocal.h b/suite/audio_quality/lib/include/audio/AudioRecordingLocal.h
new file mode 100644
index 0000000..614ed6d
--- /dev/null
+++ b/suite/audio_quality/lib/include/audio/AudioRecordingLocal.h
@@ -0,0 +1,50 @@
+/*
+ * 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_AUDIORECORDINGLOCAL_H
+#define CTSAUDIO_AUDIORECORDINGLOCAL_H
+
+#include <utils/String8.h>
+
+#include <tinyalsa/asoundlib.h>
+
+#include "AudioLocal.h"
+
+
+class AudioRecordingLocal: public AudioLocal {
+public:
+ AudioRecordingLocal(int hwId);
+ virtual ~AudioRecordingLocal();
+protected:
+ bool doPrepare(AudioHardware::SamplingRate, int samplesInOneGo);
+ bool doPlaybackOrRecord(android::sp<Buffer>& buffer);
+ void doStop();
+ void releaseHw();
+
+private:
+ int mHwId;
+ struct pcm* mPcmHandle;
+ // unit recording samples
+ int mSamples;
+ // unit recording sizes
+ int mSizes;
+ // alsa buffer size
+ int mBufferSize;
+};
+
+
+#endif // CTSAUDIO_AUDIORECORDINGLOCAL_H
diff --git a/suite/audio_quality/lib/include/audio/AudioRemote.h b/suite/audio_quality/lib/include/audio/AudioRemote.h
new file mode 100644
index 0000000..1268ee0
--- /dev/null
+++ b/suite/audio_quality/lib/include/audio/AudioRemote.h
@@ -0,0 +1,63 @@
+/*
+ * 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_AUDIOREMOTE_H
+#define CTSAUDIO_AUDIOREMOTE_H
+#include <utils/StrongPointer.h>
+#include "AudioHardware.h"
+// real implementation
+#include "RemoteAudio.h"
+
+
+// wrapper in AudioHardware interface
+class AudioRemote: public AudioHardware {
+public:
+ virtual bool prepare(AudioHardware::SamplingRate samplingRate, int volume,
+ int mode = AudioHardware::EModeVoice);
+
+protected:
+ AudioRemote(android::sp<RemoteAudio>& remote);
+ virtual ~AudioRemote() {};
+
+protected:
+ android::sp<RemoteAudio> mRemote;
+ AudioHardware::SamplingRate mSamplingRate;
+ int mVolume;
+ int mMode;
+};
+
+class AudioRemotePlayback: public AudioRemote {
+public:
+ AudioRemotePlayback(android::sp<RemoteAudio>& remote);
+ virtual ~AudioRemotePlayback() {};
+ virtual bool startPlaybackOrRecord(android::sp<Buffer>& buffer, int numberRepetition = 1);
+ virtual bool waitForCompletion();
+ virtual void stopPlaybackOrRecord();
+ bool startPlaybackForRemoteData(int id, bool stereo, int numberRepetition = 1);
+};
+
+class AudioRemoteRecording: public AudioRemote {
+public:
+ AudioRemoteRecording(android::sp<RemoteAudio>& remote);
+ virtual ~AudioRemoteRecording() {};
+ virtual bool startPlaybackOrRecord(android::sp<Buffer>& buffer, int numberRepetition = 1);
+ virtual bool waitForCompletion();
+ virtual void stopPlaybackOrRecord();
+};
+
+
+#endif // CTSAUDIO_AUDIOREMOTE_H
diff --git a/suite/audio_quality/lib/include/audio/AudioSignalFactory.h b/suite/audio_quality/lib/include/audio/AudioSignalFactory.h
new file mode 100644
index 0000000..1c985cc
--- /dev/null
+++ b/suite/audio_quality/lib/include/audio/AudioSignalFactory.h
@@ -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.
+ */
+
+
+#ifndef CTSAUDIO_AUDIOSIGNALFACTORY_H
+#define CTSAUDIO_AUDIOSIGNALFACTORY_H
+
+#include <utils/StrongPointer.h>
+
+#include "AudioHardware.h"
+#include "Buffer.h"
+/**
+ * factory for creating various audio signals
+ */
+class AudioSignalFactory {
+public:
+ static android::sp<Buffer> generateSineWave(AudioHardware::BytesPerSample BPS,
+ int maxPositive, AudioHardware::SamplingRate samplingRate, int signalFreq, int samples,
+ bool stereo = true);
+ static android::sp<Buffer> generateWhiteNoise(AudioHardware::BytesPerSample BPS,
+ int maxPositive, int samples, bool stereo = true);
+ static android::sp<Buffer> generateZeroSound(AudioHardware::BytesPerSample BPS,
+ int samples, bool stereo = true);
+};
+
+
+#endif // CTSAUDIO_AUDIOSIGNALFACTORY_H
diff --git a/suite/audio_quality/lib/include/audio/Buffer.h b/suite/audio_quality/lib/include/audio/Buffer.h
new file mode 100644
index 0000000..343c502
--- /dev/null
+++ b/suite/audio_quality/lib/include/audio/Buffer.h
@@ -0,0 +1,136 @@
+/*
+ * 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_BUFFER_H
+#define CTSAUDIO_BUFFER_H
+
+#include <stdlib.h>
+#include <string.h>
+#include <utils/String8.h>
+
+#include <utils/RefBase.h>
+
+#include <Log.h>
+
+/**
+ * Buffer passed for audio playback and recording
+ * The buffer is supposed to be used with sp to guarantee that audio thread can
+ * access it even if the client thread is dead.
+ */
+class Buffer: public virtual android::RefBase {
+public:
+ Buffer(size_t capacity, size_t size = 0, bool stereo = true);
+
+ virtual ~Buffer();
+
+ inline size_t getCapacity() {
+ return mCapacity;
+ };
+
+ inline size_t getSize() {
+ return mSize;
+ };
+
+ inline size_t getSamples() {
+ return (getSize() / (isStereo() ? 4 : 2));
+ };
+
+ inline void setSize(size_t size) {
+ mSize = size;
+ };
+
+ inline void increaseSize(size_t size) {
+ mSize += size;
+ }
+ inline char* getData() {
+ return mData;
+ };
+
+ inline void setData(char* data, size_t len) {
+ ASSERT(len <= mCapacity);
+ memcpy(mData, data, len);
+ mSize = len;
+ };
+
+ inline char* getUnhanledData() {
+ return mData + mHandled;
+ };
+
+ inline bool bufferHandled() {
+ return mSize <= mHandled;
+ };
+
+ inline void restart() {
+ mHandled = 0;
+ };
+ /// size was recorded
+ inline void increaseHandled(size_t size) {
+ mHandled += size;
+ };
+
+ inline void setHandled(size_t size) {
+ mHandled = size;
+ }
+ /// amount recorded
+ inline size_t amountHandled() {
+ return mHandled;
+ };
+
+ inline size_t amountToHandle() {
+ return mSize - mHandled;
+ };
+
+ inline bool isStereo() {
+ return mStereo;
+ };
+ enum ConvertOption {
+ EKeepCh0 = 0,
+ EKeepCh1 = 1,
+ EAverage = 2
+ };
+ /// change stereo buffer to mono
+ void changeToMono(ConvertOption option);
+ /// change mono buffer to stereo. This does not increase allocated memory.
+ /// So it will fail if capacity is not big enough.
+ bool changeToStereo();
+
+ /// save the buffer to file
+ /// extension appropriate for the data type will be appended to file name
+ bool saveToFile(const android::String8& filename);
+
+ bool operator ==(const Buffer& b) const;
+
+ /// load raw data from given file.
+ /// data format is decided by extension
+ /// .r2s: 16 bps, stereo
+ /// .r2m: 16bps, mono
+ static Buffer* loadFromFile(const android::String8& filename);
+private:
+ // max data that can be hold
+ size_t mCapacity;
+ // data stored for playback / to store for recording
+ size_t mSize;
+ // how much data was handled / recorded
+ size_t mHandled;
+ // stereo or mono
+ bool mStereo;
+ // payload
+ char* mData;
+};
+
+
+
+#endif // CTSAUDIO_BUFFER_H
diff --git a/suite/audio_quality/lib/include/audio/RemoteAudio.h b/suite/audio_quality/lib/include/audio/RemoteAudio.h
new file mode 100644
index 0000000..4c587e6
--- /dev/null
+++ b/suite/audio_quality/lib/include/audio/RemoteAudio.h
@@ -0,0 +1,151 @@
+/*
+ * 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_REMOTEAUDIO_H
+#define CTSAUDIO_REMOTEAUDIO_H
+
+#include <map>
+
+#include <utils/Looper.h>
+#include <utils/StrongPointer.h>
+#include <utils/threads.h>
+
+#include "audio/Buffer.h"
+#include "AudioProtocol.h"
+#include "ClientSocket.h"
+#include "Semaphore.h"
+
+class CommandHandler;
+/**
+ * Tcp communication runs in a separate thread,
+ * and client can communicate using public APIs
+ * Assumption: only one command at a time. No other command can come
+ * while a command is pending.
+ */
+class RemoteAudio: public android::Thread {
+public:
+
+ RemoteAudio(ClientSocket& socket);
+ virtual ~RemoteAudio();
+
+ /** launch a thread, and connect to host */
+ bool init(int port);
+ bool downloadData(const android::String8 name, android::sp<Buffer>& buffer, int& id);
+ // <0 : not found
+ int getDataId(const android::String8& name);
+ bool startPlayback(bool stereo, int samplingF, int mode, int volume,
+ int id, int numberRepetition);
+ void stopPlayback();
+ bool waitForPlaybackCompletion();
+ // buffer.getSize() determines number of samples
+ bool startRecording(bool stereo, int samplingF, int mode, int volume,
+ android::sp<Buffer>& buffer);
+ bool waitForRecordingCompletion();
+ void stopRecording();
+ /** should be called before RemoteAudio is destroyed */
+ void release();
+
+private:
+ RemoteAudio(const RemoteAudio&);
+
+ bool threadLoop();
+ void wakeClient(bool result);
+ void cleanup(bool notifyClient);
+
+ bool handlePacket();
+ static int socketRxCallback(int fd, int events, void* data);
+
+ class CommandHandler;
+ void sendCommand(android::sp<android::MessageHandler>& command);
+
+ // this is just semaphore wait without any addition
+ bool waitForCompletion(android::sp<android::MessageHandler>& command, int timeInMSec);
+ // common code for waitForXXXCompletion
+ bool waitForPlaybackOrRecordingCompletion(
+ android::sp<android::MessageHandler>& commandHandler);
+ // common code for stopXXX
+ void doStop(android::sp<android::MessageHandler>& commandHandler, AudioProtocol::CommandId id);
+
+ CommandHandler* toCommandHandler(android::sp<android::MessageHandler>& command) {
+ return reinterpret_cast<CommandHandler*>(command.get());
+ };
+
+private:
+ bool mExitRequested;
+ bool mInitResult;
+ // used only for notifying successful init
+ Semaphore mInitWait;
+
+
+ enum EventId {
+ EIdSocket = 1,
+ };
+ static const int CLIENT_WAIT_TIMEOUT_MSEC = 2000;
+ int mPort;
+ ClientSocket& mSocket;
+
+
+ android::sp<android::Looper> mLooper;
+
+ friend class CommandHandler;
+
+ class CommandHandler: public android::MessageHandler {
+ public:
+ enum ClientCommands {
+ EExit = 1,
+ };
+ CommandHandler(RemoteAudio& thread, int command)
+ : mThread(thread),
+ mMessage(command),
+ mNotifyOnReply(false),
+ mActive(false) {};
+ virtual ~CommandHandler() {};
+ void handleMessage(const android::Message& message);
+ bool timedWait(int timeInMSec) {
+ return mClientWait.timedWait(timeInMSec);
+ };
+ AudioParam& getParam() {
+ return mParam;
+ };
+ android::Message& getMessage() {
+ return mMessage;
+ };
+
+ private:
+ RemoteAudio& mThread;
+ AudioParam mParam;
+ Semaphore mClientWait;
+ android::Mutex mStateLock;
+ android::Message mMessage;
+ bool mResult;
+ bool mNotifyOnReply;
+ bool mActive;
+ friend class RemoteAudio;
+ };
+ android::sp<android::MessageHandler> mDownloadHandler;
+ android::sp<android::MessageHandler> mPlaybackHandler;
+ android::sp<android::MessageHandler> mRecordingHandler;
+
+ AudioProtocol* mCmds[AudioProtocol::ECmdLast - AudioProtocol::ECmdStart];
+ int mDownloadId;
+ std::map<int, android::sp<Buffer> > mBufferList;
+ std::map<android::String8, int> mIdMap;
+};
+
+
+
+#endif // CTSAUDIO_REMOTEAUDIO_H