summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Fitzgerald <rf@opensource.wolfsonmicro.com>2013-05-13 11:52:24 +0100
committerEric Laurent <elaurent@google.com>2013-07-24 18:39:05 -0700
commita527ffd3c2ce72048a8fae51cd399024af4439b9 (patch)
tree79424aff01ccaa60d8dbfd060bfce05d3b7bc129
parentcb2388428a54fb3040209b8134c1e2acec0801fb (diff)
downloadhardware_libhardware_legacy-a527ffd3c2ce72048a8fae51cd399024af4439b9.zip
hardware_libhardware_legacy-a527ffd3c2ce72048a8fae51cd399024af4439b9.tar.gz
hardware_libhardware_legacy-a527ffd3c2ce72048a8fae51cd399024af4439b9.tar.bz2
Code changes for audio offload support
- Share existing offload output if compatible instead of creating a new one. Hardware has limited number of offload channels (possible only 1) so we must use as few as possible - Changes to routing handling for offloaded outputs Change-Id: I11111d8f504828595bd8dbf66444cbd1202e7192 Signed-off-by: Eric Laurent <elaurent@google.com>
-rw-r--r--audio/AudioHardwareGeneric.h2
-rw-r--r--audio/AudioHardwareStub.cpp4
-rw-r--r--audio/AudioHardwareStub.h2
-rw-r--r--audio/AudioPolicyManagerBase.cpp144
-rw-r--r--include/hardware_legacy/AudioPolicyManagerBase.h14
5 files changed, 116 insertions, 50 deletions
diff --git a/audio/AudioHardwareGeneric.h b/audio/AudioHardwareGeneric.h
index 7b41e95..55498dc 100644
--- a/audio/AudioHardwareGeneric.h
+++ b/audio/AudioHardwareGeneric.h
@@ -92,6 +92,8 @@ public:
virtual status_t setParameters(const String8& keyValuePairs);
virtual String8 getParameters(const String8& keys);
virtual unsigned int getInputFramesLost() const { return 0; }
+ virtual status_t addAudioEffect(effect_handle_t effect) { return NO_ERROR; }
+ virtual status_t removeAudioEffect(effect_handle_t effect) { return NO_ERROR; }
private:
AudioHardwareGeneric *mAudioHardware;
diff --git a/audio/AudioHardwareStub.cpp b/audio/AudioHardwareStub.cpp
index 70a8309..1083889 100644
--- a/audio/AudioHardwareStub.cpp
+++ b/audio/AudioHardwareStub.cpp
@@ -204,6 +204,10 @@ String8 AudioStreamInStub::getParameters(const String8& keys)
return param.toString();
}
+AudioHardwareInterface* createAudioHardware(void) {
+ return new AudioHardwareStub();
+}
+
// ----------------------------------------------------------------------------
}; // namespace android
diff --git a/audio/AudioHardwareStub.h b/audio/AudioHardwareStub.h
index 0858f37..c5f7a80 100644
--- a/audio/AudioHardwareStub.h
+++ b/audio/AudioHardwareStub.h
@@ -58,6 +58,8 @@ public:
virtual status_t setParameters(const String8& keyValuePairs) { return NO_ERROR;}
virtual String8 getParameters(const String8& keys);
virtual unsigned int getInputFramesLost() const { return 0; }
+ virtual status_t addAudioEffect(effect_handle_t effect) { return NO_ERROR; }
+ virtual status_t removeAudioEffect(effect_handle_t effect) { return NO_ERROR; }
};
class AudioHardwareStub : public AudioHardwareBase
diff --git a/audio/AudioPolicyManagerBase.cpp b/audio/AudioPolicyManagerBase.cpp
index e6e498f..56ec96e 100644
--- a/audio/AudioPolicyManagerBase.cpp
+++ b/audio/AudioPolicyManagerBase.cpp
@@ -37,6 +37,7 @@
#include <hardware/audio.h>
#include <math.h>
#include <hardware_legacy/audio_policy_conf.h>
+#include <cutils/properties.h>
namespace android_audio_legacy {
@@ -161,10 +162,12 @@ status_t AudioPolicyManagerBase::setDeviceConnectionState(audio_devices_t device
// outputs must be closed after checkOutputForAllStrategies() is executed
if (!outputs.isEmpty()) {
for (size_t i = 0; i < outputs.size(); i++) {
+ AudioOutputDescriptor *desc = mOutputs.valueFor(outputs[i]);
// close unused outputs after device disconnection or direct outputs that have been
// opened by checkOutputsForDevice() to query dynamic parameters
if ((state == AudioSystem::DEVICE_STATE_UNAVAILABLE) ||
- (mOutputs.valueFor(outputs[i])->mFlags & AUDIO_OUTPUT_FLAG_DIRECT)) {
+ (((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) &&
+ (desc->mDirectOpenCount == 0))) {
closeOutput(outputs[i]);
}
}
@@ -491,14 +494,24 @@ AudioPolicyManagerBase::IOProfile *AudioPolicyManagerBase::getProfileForDirectOu
continue;
}
for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++) {
- IOProfile *profile = mHwModules[i]->mOutputProfiles[j];
- if (profile->isCompatibleProfile(device, samplingRate, format,
+ IOProfile *profile = mHwModules[i]->mOutputProfiles[j];
+ if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
+ if (profile->isCompatibleProfile(device, samplingRate, format,
+ channelMask,
+ AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
+ if (mAvailableOutputDevices & profile->mSupportedDevices) {
+ return mHwModules[i]->mOutputProfiles[j];
+ }
+ }
+ } else if (flags & AUDIO_OUTPUT_FLAG_DIRECT) {
+ if (profile->isCompatibleProfile(device, samplingRate, format,
channelMask,
AUDIO_OUTPUT_FLAG_DIRECT)) {
- if (mAvailableOutputDevices & profile->mSupportedDevices) {
- return mHwModules[i]->mOutputProfiles[j];
- }
- }
+ if (mAvailableOutputDevices & profile->mSupportedDevices) {
+ return mHwModules[i]->mOutputProfiles[j];
+ }
+ }
+ }
}
}
return 0;
@@ -515,8 +528,8 @@ audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type str
uint32_t latency = 0;
routing_strategy strategy = getStrategy((AudioSystem::stream_type)stream);
audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/);
- ALOGV("getOutput() stream %d, samplingRate %d, format %d, channelMask %x, flags %x",
- stream, samplingRate, format, channelMask, flags);
+ ALOGV("getOutput() device %d, stream %d, samplingRate %d, format %x, channelMask %x, flags %x",
+ device, stream, samplingRate, format, channelMask, flags);
#ifdef AUDIO_POLICY_TEST
if (mCurOutput != 0) {
@@ -552,6 +565,13 @@ audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type str
#endif //AUDIO_POLICY_TEST
// open a direct output if required by specified parameters
+ //force direct flag if offload flag is set: offloading implies a direct output stream
+ // and all common behaviors are driven by checking only the direct flag
+ // this should normally be set appropriately in the policy configuration file
+ if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
+ flags = (AudioSystem::output_flags)(flags | AUDIO_OUTPUT_FLAG_DIRECT);
+ }
+
IOProfile *profile = getProfileForDirectOutput(device,
samplingRate,
format,
@@ -569,7 +589,7 @@ audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type str
(format == outputDesc->mFormat) &&
(channelMask == outputDesc->mChannelMask)) {
outputDesc->mDirectOpenCount++;
- ALOGV("getOutput() reusing direct output %d", output);
+ ALOGV("getOutput() reusing direct output %d", mOutputs.keyAt(i));
return mOutputs.keyAt(i);
}
}
@@ -584,8 +604,7 @@ audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type str
outputDesc->mFormat = (audio_format_t)format;
outputDesc->mChannelMask = (audio_channel_mask_t)channelMask;
outputDesc->mLatency = 0;
- outputDesc->mFlags =(audio_output_flags_t)
- (outputDesc->mFlags | flags | AUDIO_OUTPUT_FLAG_DIRECT);
+ outputDesc->mFlags =(audio_output_flags_t) (outputDesc->mFlags | flags);
outputDesc->mRefCount[stream] = 0;
outputDesc->mStopTime[stream] = 0;
outputDesc->mDirectOpenCount = 1;
@@ -595,7 +614,8 @@ audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type str
&outputDesc->mFormat,
&outputDesc->mChannelMask,
&outputDesc->mLatency,
- outputDesc->mFlags);
+ outputDesc->mFlags,
+ offloadInfo);
// only accept an output with the requested parameters
if (output == 0 ||
@@ -622,13 +642,15 @@ audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type str
// open a non direct output
- // get which output is suitable for the specified stream. The actual routing change will happen
- // when startOutput() will be called
- SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(device, mOutputs);
+ // for non direct outputs, only PCM is supported
+ if (audio_is_linear_pcm((audio_format_t)format)) {
+ // get which output is suitable for the specified stream. The actual
+ // routing change will happen when startOutput() will be called
+ SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(device, mOutputs);
- output = selectOutput(outputs, flags);
-
- ALOGW_IF((output ==0), "getOutput() could not find output for stream %d, samplingRate %d,"
+ output = selectOutput(outputs, flags);
+ }
+ ALOGW_IF((output == 0), "getOutput() could not find output for stream %d, samplingRate %d,"
"format %d, channels %x, flags %x", stream, samplingRate, format, channelMask, flags);
ALOGV("getOutput() returns output %d", output);
@@ -790,7 +812,7 @@ status_t AudioPolicyManagerBase::stopOutput(audio_io_handle_t output,
if (curOutput != output &&
desc->isActive() &&
outputDesc->sharesHwModuleWith(desc) &&
- newDevice != desc->device()) {
+ (newDevice != desc->device())) {
setOutputDevice(curOutput,
getNewDevice(curOutput, false /*fromCache*/),
true,
@@ -841,7 +863,6 @@ void AudioPolicyManagerBase::releaseOutput(audio_io_handle_t output)
closeOutput(output);
}
}
-
}
audio_io_handle_t AudioPolicyManagerBase::getInput(int inputSource,
@@ -1319,10 +1340,54 @@ status_t AudioPolicyManagerBase::dump(int fd)
return NO_ERROR;
}
+// This function checks for the parameters which can be offloaded.
+// This can be enhanced depending on the capability of the DSP and policy
+// of the system.
bool AudioPolicyManagerBase::isOffloadSupported(const audio_offload_info_t& offloadInfo)
{
- // Stub implementation
- return false;
+ ALOGV("isOffloadSupported: SR=%u, CM=0x%x, Format=0x%x, StreamType=%d,"
+ " BitRate=%u, duration=%lld us, has_video=%d",
+ offloadInfo.sample_rate, offloadInfo.channel_mask,
+ offloadInfo.format,
+ offloadInfo.stream_type, offloadInfo.bit_rate, offloadInfo.duration_us,
+ offloadInfo.has_video);
+
+ // Check if offload has been disabled
+ char propValue[PROPERTY_VALUE_MAX];
+ if (property_get("audio.offload.disable", propValue, "0")) {
+ if (atoi(propValue) != 0) {
+ ALOGV("offload disabled by audio.offload.disable=%s", propValue );
+ return false;
+ }
+ }
+
+ // Check if stream type is music, then only allow offload as of now.
+ if (offloadInfo.stream_type != AUDIO_STREAM_MUSIC)
+ {
+ ALOGV("isOffloadSupported: stream_type != MUSIC returning false");
+ return false;
+ }
+
+ //If duration is less than minimum value defined in property, return false
+ if (property_get("audio.offload.min.duration.secs", propValue, NULL)) {
+ if (offloadInfo.duration_us < (atoi(propValue) * 1000000 )) {
+ ALOGV("Offload denied by duration < audio.offload.min.duration.secs(=%s)", propValue);
+ return false;
+ }
+ } else if (offloadInfo.duration_us < OFFLOAD_DEFAULT_MIN_DURATION_SECS * 1000000) {
+ ALOGV("Offload denied by duration < default min(=%u)", OFFLOAD_DEFAULT_MIN_DURATION_SECS);
+ return false;
+ }
+
+ // See if there is a profile to support this.
+ // AUDIO_DEVICE_NONE
+ IOProfile *profile = getProfileForDirectOutput(AUDIO_DEVICE_NONE /*ignore device */,
+ offloadInfo.sample_rate,
+ offloadInfo.format,
+ offloadInfo.channel_mask,
+ AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD);
+ ALOGV("isOffloadSupported() profile %sfound", profile != NULL ? "" : "NOT ");
+ return (profile != NULL);
}
// ----------------------------------------------------------------------------
@@ -1368,11 +1433,14 @@ AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clien
continue;
}
// open all output streams needed to access attached devices
+ // except for direct output streams that are only opened when they are actually
+ // required by an app.
for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++)
{
const IOProfile *outProfile = mHwModules[i]->mOutputProfiles[j];
- if (outProfile->mSupportedDevices & mAttachedOutputDevices) {
+ if ((outProfile->mSupportedDevices & mAttachedOutputDevices) &&
+ ((outProfile->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) == 0)) {
AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor(outProfile);
outputDesc->mDevice = (audio_devices_t)(mDefaultOutputDevice &
outProfile->mSupportedDevices);
@@ -3011,17 +3079,6 @@ bool AudioPolicyManagerBase::isStateInCall(int state) {
(state == AudioSystem::MODE_IN_COMMUNICATION));
}
-bool AudioPolicyManagerBase::needsDirectOuput(audio_stream_type_t stream,
- uint32_t samplingRate,
- audio_format_t format,
- audio_channel_mask_t channelMask,
- audio_output_flags_t flags,
- audio_devices_t device)
-{
- return ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) ||
- (format != 0 && !AudioSystem::isLinearPCM(format)));
-}
-
uint32_t AudioPolicyManagerBase::getMaxEffectsCpuLoad()
{
return MAX_EFFECTS_CPU_LOAD;
@@ -3164,7 +3221,7 @@ status_t AudioPolicyManagerBase::AudioOutputDescriptor::dump(int fd)
snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate);
result.append(buffer);
- snprintf(buffer, SIZE, " Format: %d\n", mFormat);
+ snprintf(buffer, SIZE, " Format: %08x\n", mFormat);
result.append(buffer);
snprintf(buffer, SIZE, " Channels: %08x\n", mChannelMask);
result.append(buffer);
@@ -3402,7 +3459,7 @@ void AudioPolicyManagerBase::IOProfile::dump(int fd)
snprintf(buffer, SIZE, " - channel masks: ");
result.append(buffer);
for (size_t i = 0; i < mChannelMasks.size(); i++) {
- snprintf(buffer, SIZE, "%04x", mChannelMasks[i]);
+ snprintf(buffer, SIZE, "0x%04x", mChannelMasks[i]);
result.append(buffer);
result.append(i == (mChannelMasks.size() - 1) ? "\n" : ", ");
}
@@ -3410,14 +3467,14 @@ void AudioPolicyManagerBase::IOProfile::dump(int fd)
snprintf(buffer, SIZE, " - formats: ");
result.append(buffer);
for (size_t i = 0; i < mFormats.size(); i++) {
- snprintf(buffer, SIZE, "%d", mFormats[i]);
+ snprintf(buffer, SIZE, "0x%08x", mFormats[i]);
result.append(buffer);
result.append(i == (mFormats.size() - 1) ? "\n" : ", ");
}
- snprintf(buffer, SIZE, " - devices: %04x\n", mSupportedDevices);
+ snprintf(buffer, SIZE, " - devices: 0x%04x\n", mSupportedDevices);
result.append(buffer);
- snprintf(buffer, SIZE, " - flags: %04x\n", mFlags);
+ snprintf(buffer, SIZE, " - flags: 0x%04x\n", mFlags);
result.append(buffer);
write(fd, result.string(), result.size());
@@ -3518,6 +3575,13 @@ audio_output_flags_t AudioPolicyManagerBase::parseFlagNames(char *name)
}
flagName = strtok(NULL, "|");
}
+ //force direct flag if offload flag is set: offloading implies a direct output stream
+ // and all common behaviors are driven by checking only the direct flag
+ // this should normally be set appropriately in the policy configuration file
+ if ((flag & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
+ flag |= AUDIO_OUTPUT_FLAG_DIRECT;
+ }
+
return (audio_output_flags_t)flag;
}
diff --git a/include/hardware_legacy/AudioPolicyManagerBase.h b/include/hardware_legacy/AudioPolicyManagerBase.h
index cb2a7fa..e580e1e 100644
--- a/include/hardware_legacy/AudioPolicyManagerBase.h
+++ b/include/hardware_legacy/AudioPolicyManagerBase.h
@@ -52,6 +52,10 @@ namespace android_audio_legacy {
#define NUM_VOL_CURVE_KNEES 2
+// Default minimum length allowed for offloading a compressed track
+// Can be overridden by the audio.offload.min.duration.secs property
+#define OFFLOAD_DEFAULT_MIN_DURATION_SECS 5
+
// ----------------------------------------------------------------------------
// AudioPolicyManagerBase implements audio policy manager behavior common to all platforms.
// Each platform must implement an AudioPolicyManager class derived from AudioPolicyManagerBase
@@ -444,16 +448,6 @@ protected:
void updateDevicesAndOutputs();
- // true if current platform requires a specific output to be opened for this particular
- // set of parameters. This function is called by getOutput() and is implemented by platform
- // specific audio policy manager.
- virtual bool needsDirectOuput(audio_stream_type_t stream,
- uint32_t samplingRate,
- audio_format_t format,
- audio_channel_mask_t channelMask,
- audio_output_flags_t flags,
- audio_devices_t device);
-
virtual uint32_t getMaxEffectsCpuLoad();
virtual uint32_t getMaxEffectsMemory();
#ifdef AUDIO_POLICY_TEST