audiosignal工厂
#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
抽象类的工厂方法GenericFactory
#include <getopt.h>
#include <stdio.h>
#include <utils/String8.h>
#include <UniquePtr.h>
#include "GenericFactory.h"
#include "Log.h"
#include "Report.h"
#include "Settings.h"
#include "task/TaskGeneric.h"
#include "task/ModelBuilder.h"
// For flushing report and log before exiting
class CleanupStatics {//注释1
public:
CleanupStatics() {
}
~CleanupStatics() {
Log::Finalize();
Report::Finalize();
// create zip file after log and report files are closed.
android::String8 reportDirPath =
Settings::Instance()->getSetting(Settings::EREPORT_FILE).getPathDir();
android::String8 zipFilename = reportDirPath.getPathLeaf();
android::String8 command = android::String8::format("cd %s;zip -r ../%s.zip *",
reportDirPath.string(), zipFilename.string());
fprintf(stderr, "\n\nexecuting %s\n", command.string());
if (system(command.string()) == -1) {
fprintf(stderr, "cannot create zip file with command %s\n", command.string());
}
Settings::Finalize();
}
};
void usage(char* bin)
{
fprintf(stderr, "%s [-l log_level][-s serial] test_xml\n", bin);
}
int main(int argc, char *argv[])
{
if (argc < 2) {
fprintf(stderr, "%s [-l log_level][-s serial] test_xml\n", argv[0]);
return 1;
}
int logLevel = Log::ELogW;
char* serial = NULL;
int opt;
while ((opt = getopt(argc, argv, "l:s:")) != -1) {
switch (opt) {
case 'l':
logLevel = atoi(optarg);
break;
case 's':
serial = optarg;
break;
default:
usage(argv[0]);
return 1;
}
}
if (optind >= argc) {
usage(argv[0]);
return 1;
}
android::String8 xmlFile(argv[optind]);
android::String8 dirName;
if (!FileUtil::prepare(dirName)) {
fprintf(stderr, "cannot prepare report dir");
return 1;
}
UniquePtr<CleanupStatics> staticStuffs(new CleanupStatics());
if (Settings::Instance() == NULL) {
fprintf(stderr, "caanot create Settings");
return 1;
}
if (serial != NULL) {
android::String8 strSerial(serial);
Settings::Instance()->addSetting(Settings::EADB, strSerial);
}
if (Log::Instance(dirName.string()) == NULL) {
fprintf(stderr, "cannot create Log");
return 1;
}
Log::Instance()->setLogLevel((Log::LogLevel)logLevel);
// Log can be used from here
if (Report::Instance(dirName.string()) == NULL) {
LOGE("cannot create log");
return 1;
}
GenericFactory factory;
ClientInterface* client = factory.createClientInterface();//注释2
if (client == NULL) {
fprintf(stderr, "cannot create ClientInterface");
return 1;
}
if (!client->init(Settings::Instance()->getSetting(Settings::EADB))) {
fprintf(stderr, "cannot init ClientInterface");
return 1;
}
android::String8 deviceInfo;
if (!client->getAudio()->getDeviceInfo(deviceInfo)) {//注释3
fprintf(stderr, "cannot get device info");
return 1;
}
delete client; // release so that it can be used in tests
Settings::Instance()->addSetting(Settings::EDEVICE_INFO, deviceInfo);
ModelBuilder modelBuilder;
UniquePtr<TaskGeneric> topTask(modelBuilder.parseTestDescriptionXml(xmlFile));
if (topTask.get() == NULL) {
LOGE("Parsing of %x failed", xmlFile.string());
return 1;
}
Settings::Instance()->addSetting(Settings::ETEST_XML, xmlFile);
topTask->run();
return 0;
}
注释1:
CleanupStatics用于程序退出时flush报告和日志
注释2:ClientInterface
#ifndef CTSAUDIO_CLIENTINTERFACE_H
#define CTSAUDIO_CLIENTINTERFACE_H
#include <utils/String8.h>
#include <utils/StrongPointer.h>
#include "audio/RemoteAudio.h"
#include "ClientSocket.h"
class ClientInterface {
public:
virtual ~ClientInterface() {};
/**
* launch client and perform initial connection
* @param param parameter for connection. It will be device serial number or zero length string
*/
virtual bool init(const android::String8& param) = 0;
virtual ClientSocket& getSocket() = 0;
virtual android::sp<RemoteAudio>& getAudio() = 0;
};
#endif
测试程序
#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, getDeviceInfoTest) {
ClientImpl* client = reinterpret_cast<ClientImpl*>(mClient);
android::sp<RemoteAudio>& audio(client->getAudio());
android::String8 info;
ASSERT_TRUE(audio->getDeviceInfo(info));
LOGD("device info %s", info.string());
}
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));
}
生成ClientInterface使用到的工厂方法GenericFactory
#ifndef CTSAUDIO_GENERIC_FACTORY_H
#define CTSAUDIO_GENERIC_FACTORY_H
#include "task/TaskGeneric.h"
#include "ClientInterface.h"
/**
* Factory methods for all abstract classes
*/
class GenericFactory {
public:
virtual ClientInterface* createClientInterface();
virtual TaskGeneric* createTask(TaskGeneric::TaskType type);
};
#endif
注释3:
根据RemoteAudio的指针获取设备信息