aaudio: add setPerformanceMode()
The performance mode affects the latency and the implementation of the
data path.
MMAP is still disabled for now.
Bug: 37867485
Test: write_sine.cpp
Change-Id: I9bf5d5d13d1047d5ace69bd5ebdce7b6d65c14e7
Signed-off-by: Phil Burk <philburk@google.com>
diff --git a/media/libaaudio/src/client/AudioStreamInternal.h b/media/libaaudio/src/client/AudioStreamInternal.h
index 18a55cf..a43f6c5 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.h
+++ b/media/libaaudio/src/client/AudioStreamInternal.h
@@ -90,6 +90,11 @@
// Called internally from 'C'
void *callbackLoop();
+
+ bool isMMap() override {
+ return true;
+ }
+
protected:
aaudio_result_t processCommands();
diff --git a/media/libaaudio/src/core/AAudioAudio.cpp b/media/libaaudio/src/core/AAudioAudio.cpp
index e5239e8..59032d5 100644
--- a/media/libaaudio/src/core/AAudioAudio.cpp
+++ b/media/libaaudio/src/core/AAudioAudio.cpp
@@ -114,8 +114,15 @@
return AAUDIO_OK;
}
+AAUDIO_API void AAudioStreamBuilder_setPerformanceMode(AAudioStreamBuilder* builder,
+ aaudio_performance_mode_t mode)
+{
+ AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
+ streamBuilder->setPerformanceMode(mode);
+}
+
AAUDIO_API void AAudioStreamBuilder_setDeviceId(AAudioStreamBuilder* builder,
- int32_t deviceId)
+ int32_t deviceId)
{
AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
streamBuilder->setDeviceId(deviceId);
@@ -403,6 +410,12 @@
return audioStream->getXRunCount();
}
+AAUDIO_API aaudio_performance_mode_t AAudioStream_getPerformanceMode(AAudioStream* stream)
+{
+ AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
+ return audioStream->getPerformanceMode();
+}
+
AAUDIO_API int32_t AAudioStream_getDeviceId(AAudioStream* stream)
{
AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index 598fbaa..c3cf27f 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -47,6 +47,8 @@
mSharingMode = builder.getSharingMode();
mSharingModeMatchRequired = builder.isSharingModeMatchRequired();
+ mPerformanceMode = builder.getPerformanceMode();
+
// callbacks
mFramesPerDataCallback = builder.getFramesPerDataCallback();
mDataCallbackProc = builder.getDataCallbackProc();
@@ -73,6 +75,16 @@
return AAUDIO_ERROR_UNEXPECTED_VALUE;
}
+ switch(mPerformanceMode) {
+ case AAUDIO_PERFORMANCE_MODE_NONE:
+ case AAUDIO_PERFORMANCE_MODE_POWER_SAVING:
+ case AAUDIO_PERFORMANCE_MODE_LOW_LATENCY:
+ break;
+ default:
+ ALOGE("AudioStream::open(): illegal performanceMode %d", mPerformanceMode);
+ return AAUDIO_ERROR_UNEXPECTED_VALUE;
+ }
+
return AAUDIO_OK;
}
diff --git a/media/libaaudio/src/core/AudioStream.h b/media/libaaudio/src/core/AudioStream.h
index 74a1f77..c49b46b 100644
--- a/media/libaaudio/src/core/AudioStream.h
+++ b/media/libaaudio/src/core/AudioStream.h
@@ -134,6 +134,10 @@
return mState == AAUDIO_STREAM_STATE_STARTING || mState == AAUDIO_STREAM_STATE_STARTED;
}
+ virtual bool isMMap() {
+ return false;
+ }
+
aaudio_result_t getSampleRate() const {
return mSampleRate;
}
@@ -146,6 +150,14 @@
return mSamplesPerFrame;
}
+ virtual int32_t getPerformanceMode() const {
+ return mPerformanceMode;
+ }
+
+ void setPerformanceMode(aaudio_performance_mode_t performanceMode) {
+ mPerformanceMode = performanceMode;
+ }
+
int32_t getDeviceId() const {
return mDeviceId;
}
@@ -293,6 +305,8 @@
aaudio_direction_t mDirection = AAUDIO_DIRECTION_OUTPUT;
aaudio_stream_state_t mState = AAUDIO_STREAM_STATE_UNINITIALIZED;
+ aaudio_performance_mode_t mPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE;
+
// callback ----------------------------------
AAudioStream_dataCallback mDataCallbackProc = nullptr; // external callback functions
diff --git a/media/libaaudio/src/core/AudioStreamBuilder.cpp b/media/libaaudio/src/core/AudioStreamBuilder.cpp
index d51eeb3..9bc2ef2 100644
--- a/media/libaaudio/src/core/AudioStreamBuilder.cpp
+++ b/media/libaaudio/src/core/AudioStreamBuilder.cpp
@@ -47,67 +47,80 @@
AudioStreamBuilder::~AudioStreamBuilder() {
}
+static aaudio_result_t builder_createStream(aaudio_direction_t direction,
+ aaudio_sharing_mode_t sharingMode,
+ bool tryMMap,
+ AudioStream **audioStreamPtr) {
+ *audioStreamPtr = nullptr;
+ aaudio_result_t result = AAUDIO_OK;
+ switch (direction) {
+
+ case AAUDIO_DIRECTION_INPUT:
+ if (sharingMode == AAUDIO_SHARING_MODE_SHARED) {
+ *audioStreamPtr = new AudioStreamRecord();
+ } else {
+ ALOGE("AudioStreamBuilder(): bad sharing mode = %d for input", sharingMode);
+ result = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
+ }
+ break;
+
+ case AAUDIO_DIRECTION_OUTPUT:
+ if (tryMMap) {
+ // TODO use a singleton for the AAudioBinderClient
+ AAudioBinderClient *aaudioClient = new AAudioBinderClient();
+ *audioStreamPtr = new AudioStreamInternal(*aaudioClient, false);
+ } else {
+ *audioStreamPtr = new AudioStreamTrack();
+ }
+ break;
+
+ default:
+ ALOGE("AudioStreamBuilder(): bad direction = %d", direction);
+ result = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
+ }
+ return result;
+}
+
aaudio_result_t AudioStreamBuilder::build(AudioStream** streamPtr) {
- AudioStream* audioStream = nullptr;
- AAudioBinderClient *aaudioClient = nullptr;
- const aaudio_sharing_mode_t sharingMode = getSharingMode();
+ aaudio_sharing_mode_t sharingMode = getSharingMode();
+ if ((sharingMode == AAUDIO_SHARING_MODE_EXCLUSIVE) && (MMAP_EXCLUSIVE_ENABLED == 0)) {
+ ALOGE("AudioStreamBuilder(): EXCLUSIVE sharing mode not supported");
+ return AAUDIO_ERROR_UNAVAILABLE;
+ }
- switch (getDirection()) {
+ AudioStream *audioStream = nullptr;
+ *streamPtr = nullptr;
- case AAUDIO_DIRECTION_INPUT:
- switch (sharingMode) {
- case AAUDIO_SHARING_MODE_SHARED:
- audioStream = new(std::nothrow) AudioStreamRecord();
- break;
- default:
- ALOGE("AudioStreamBuilder(): bad sharing mode = %d", sharingMode);
- return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
- break;
+ bool tryMMap = (sharingMode == AAUDIO_SHARING_MODE_SHARED) && MMAP_SHARED_ENABLED;
+ aaudio_result_t result = builder_createStream(getDirection(), sharingMode,
+ tryMMap, &audioStream);
+ if (result == AAUDIO_OK) {
+ // Open the stream using the parameters from the builder.
+ result = audioStream->open(*this);
+ if (result == AAUDIO_OK) {
+ *streamPtr = audioStream;
+ } else {
+ bool isMMap = audioStream->isMMap();
+ delete audioStream;
+ audioStream = nullptr;
+
+ if (isMMap) {
+ ALOGD("AudioStreamBuilder.build() MMAP stream did not open so try Legacy path");
+ // If MMAP stream failed to open then TRY using a legacy stream.
+ result = builder_createStream(getDirection(), sharingMode,
+ false, &audioStream);
+ if (result == AAUDIO_OK) {
+ result = audioStream->open(*this);
+ if (result == AAUDIO_OK) {
+ *streamPtr = audioStream;
+ } else {
+ delete audioStream;
+ }
+ }
+ }
}
- break;
-
- case AAUDIO_DIRECTION_OUTPUT:
- switch (sharingMode) {
- case AAUDIO_SHARING_MODE_SHARED:
-#if MMAP_SHARED_ENABLED
- aaudioClient = new AAudioBinderClient();
- audioStream = new(std::nothrow) AudioStreamInternal(*aaudioClient, false);
-#else
- audioStream = new(std::nothrow) AudioStreamTrack();
-#endif
- break;
-#if MMAP_EXCLUSIVE_ENABLED
- case AAUDIO_SHARING_MODE_EXCLUSIVE:
- aaudioClient = new AAudioBinderClient();
- audioStream = new(std::nothrow) AudioStreamInternal(*aaudioClient, false);
- break;
-#endif
- default:
- ALOGE("AudioStreamBuilder(): bad sharing mode = %d", sharingMode);
- return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
- break;
- }
- break;
-
- default:
- ALOGE("AudioStreamBuilder(): bad direction = %d", getDirection());
- return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
- break;
}
- if (audioStream == nullptr) {
- delete aaudioClient;
- return AAUDIO_ERROR_NO_MEMORY;
- }
- ALOGD("AudioStreamBuilder(): created audioStream = %p", audioStream);
- // TODO maybe move this out of build and pass the builder to the constructors
- // Open the stream using the parameters from the builder.
- const aaudio_result_t result = audioStream->open(*this);
- if (result != AAUDIO_OK) {
- delete audioStream;
- } else {
- *streamPtr = audioStream;
- }
- ALOGD("AudioStreamBuilder(): return %d", result);
+ ALOGD("AudioStreamBuilder(): returned %d", result);
return result;
}
diff --git a/media/libaaudio/src/core/AudioStreamBuilder.h b/media/libaaudio/src/core/AudioStreamBuilder.h
index 25baf4c..569ca63 100644
--- a/media/libaaudio/src/core/AudioStreamBuilder.h
+++ b/media/libaaudio/src/core/AudioStreamBuilder.h
@@ -100,6 +100,15 @@
return this;
}
+ int32_t getPerformanceMode() const {
+ return mPerformanceMode;
+ }
+
+ AudioStreamBuilder* setPerformanceMode(aaudio_performance_mode_t performanceMode) {
+ mPerformanceMode = performanceMode;
+ return this;
+ }
+
int32_t getDeviceId() const {
return mDeviceId;
}
@@ -157,14 +166,15 @@
aaudio_result_t build(AudioStream **streamPtr);
private:
- int32_t mSamplesPerFrame = AAUDIO_UNSPECIFIED;
- int32_t mSampleRate = AAUDIO_UNSPECIFIED;
- int32_t mDeviceId = AAUDIO_DEVICE_UNSPECIFIED;
- aaudio_sharing_mode_t mSharingMode = AAUDIO_SHARING_MODE_SHARED;
- bool mSharingModeMatchRequired = false; // must match sharing mode requested
- aaudio_audio_format_t mFormat = AAUDIO_FORMAT_UNSPECIFIED;
- aaudio_direction_t mDirection = AAUDIO_DIRECTION_OUTPUT;
- int32_t mBufferCapacity = AAUDIO_UNSPECIFIED;
+ int32_t mSamplesPerFrame = AAUDIO_UNSPECIFIED;
+ int32_t mSampleRate = AAUDIO_UNSPECIFIED;
+ int32_t mDeviceId = AAUDIO_DEVICE_UNSPECIFIED;
+ aaudio_sharing_mode_t mSharingMode = AAUDIO_SHARING_MODE_SHARED;
+ bool mSharingModeMatchRequired = false; // must match sharing mode requested
+ aaudio_audio_format_t mFormat = AAUDIO_FORMAT_UNSPECIFIED;
+ aaudio_direction_t mDirection = AAUDIO_DIRECTION_OUTPUT;
+ int32_t mBufferCapacity = AAUDIO_UNSPECIFIED;
+ aaudio_performance_mode_t mPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE;
AAudioStream_dataCallback mDataCallbackProc = nullptr; // external callback functions
void *mDataCallbackUserData = nullptr;
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.cpp b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
index b71b74a..b4b1c04 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
@@ -32,7 +32,6 @@
// Arbitrary and somewhat generous number of bursts.
#define DEFAULT_BURSTS_PER_BUFFER_CAPACITY 8
-static const bool FAST_TRACKS_ENABLED = true;
/*
* Create a stream that uses the AudioTrack.
@@ -69,17 +68,29 @@
ALOGD("AudioStreamTrack::open(), samplesPerFrame = %d, channelMask = 0x%08x",
samplesPerFrame, channelMask);
- // TODO add more performance options
- audio_output_flags_t flags = FAST_TRACKS_ENABLED
- ? AUDIO_OUTPUT_FLAG_FAST
- : AUDIO_OUTPUT_FLAG_NONE;
+ audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE;
+ switch(getPerformanceMode()) {
+ case AAUDIO_PERFORMANCE_MODE_LOW_LATENCY:
+ // Bypass the normal mixer and go straight to the FAST mixer.
+ flags = (audio_output_flags_t)(AUDIO_OUTPUT_FLAG_FAST | AUDIO_OUTPUT_FLAG_RAW);
+ break;
+
+ case AAUDIO_PERFORMANCE_MODE_POWER_SAVING:
+ // This uses a mixer that wakes up less often than the FAST mixer.
+ flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
+ break;
+
+ case AAUDIO_PERFORMANCE_MODE_NONE:
+ default:
+ // No flags. Use a normal mixer in front of the FAST mixer.
+ break;
+ }
int32_t frameCount = builder.getBufferCapacity();
ALOGD("AudioStreamTrack::open(), requested buffer capacity %d", frameCount);
int32_t notificationFrames = 0;
- // TODO implement an unspecified AudioTrack format then use that.
audio_format_t format = (getFormat() == AAUDIO_FORMAT_UNSPECIFIED)
? AUDIO_FORMAT_PCM_FLOAT
: AAudioConvert_aaudioToAndroidDataFormat(getFormat());