audio policy: support platforms with no audio devices
Remove requirement to declare an AUDIO_DEVICE_OUT_SPEAKER device
for platforms without audio output.
By convention:
- platforms without audio output should declare a single output
device of type AUDIO_DEVICE_OUT_STUB also declared as default
output device
- platforms without audio input should declare a single input
device of type AUDIO_DEVICE_IN_STUB
Platforms with no audio at all can use stub audio policy configuration
file and audio HAL with the following instructions in device.mk file:
USE_XML_AUDIO_POLICY_CONF := 1
PRODUCT_PACKAGES += \
audio.stub.default
PRODUCT_COPY_FILES += \
frameworks/av/services/audiopolicy/config/audio_policy_configuration_stub.xml:system/etc/audio_policy_configuration.xml
Bug: 25075342
Change-Id: Id700978559427edd3c7cc38d98f2fd52928367ed
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index b1347f4..a215b95 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -158,14 +158,14 @@
int indexMax) = 0;
// sets the new stream volume at a level corresponding to the supplied index for the
- // supplied device. By convention, specifying AUDIO_DEVICE_OUT_DEFAULT means
+ // supplied device. By convention, specifying AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME means
// setting volume for all devices
virtual status_t setStreamVolumeIndex(audio_stream_type_t stream,
int index,
audio_devices_t device) = 0;
// retrieve current volume index for the specified stream and the
- // specified device. By convention, specifying AUDIO_DEVICE_OUT_DEFAULT means
+ // specified device. By convention, specifying AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME means
// querying the volume of the active device.
virtual status_t getStreamVolumeIndex(audio_stream_type_t stream,
int *index,
diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h
index f73548d..55ee91f 100755
--- a/services/audiopolicy/common/include/policy.h
+++ b/services/audiopolicy/common/include/policy.h
@@ -47,6 +47,23 @@
#define APM_AUDIO_DEVICE_IN_MATCH_ADDRESS_ALL (AUDIO_DEVICE_IN_REMOTE_SUBMIX|AUDIO_DEVICE_IN_BUS)
/**
+ * Stub audio output device. Used in policy configuration file on platforms without audio outputs.
+ * This alias value to AUDIO_DEVICE_OUT_DEFAULT is only used in the audio policy context.
+ */
+#define AUDIO_DEVICE_OUT_STUB AUDIO_DEVICE_OUT_DEFAULT
+/**
+ * Stub audio input device. Used in policy configuration file on platforms without audio inputs.
+ * This alias value to AUDIO_DEVICE_IN_DEFAULT is only used in the audio policy context.
+ */
+#define AUDIO_DEVICE_IN_STUB AUDIO_DEVICE_IN_DEFAULT
+/**
+ * Alias to AUDIO_DEVICE_OUT_DEFAULT defined for clarification when this value is used by volume
+ * control APIs (e.g setStreamVolumeIndex().
+ */
+#define AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME AUDIO_DEVICE_OUT_DEFAULT
+
+
+/**
* Check if the state given correspond to an in call state.
* @TODO find a better name for widely call state
*
diff --git a/services/audiopolicy/common/managerdefinitions/include/VolumeCurve.h b/services/audiopolicy/common/managerdefinitions/include/VolumeCurve.h
index 7c486c8..10f0766 100644
--- a/services/audiopolicy/common/managerdefinitions/include/VolumeCurve.h
+++ b/services/audiopolicy/common/managerdefinitions/include/VolumeCurve.h
@@ -74,7 +74,7 @@
public:
VolumeCurvesForStream() : mIndexMin(0), mIndexMax(1), mCanBeMuted(true)
{
- mIndexCur.add(AUDIO_DEVICE_OUT_DEFAULT, 0);
+ mIndexCur.add(AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME, 0);
}
sp<VolumeCurve> getCurvesFor(device_category device) const
@@ -88,9 +88,9 @@
int getVolumeIndex(audio_devices_t device) const
{
device = Volume::getDeviceForVolume(device);
- // there is always a valid entry for AUDIO_DEVICE_OUT_DEFAULT
+ // there is always a valid entry for AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME
if (mIndexCur.indexOfKey(device) < 0) {
- device = AUDIO_DEVICE_OUT_DEFAULT;
+ device = AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME;
}
return mIndexCur.valueFor(device);
}
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp
index b8c0550..f382dec 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp
@@ -128,14 +128,35 @@
size_t patchesWritten = 0;
size_t patchesMax = *num_patches;
- for (size_t i = 0; i < size() && patchesWritten < patchesMax; i++) {
- const sp<AudioPatch> patch = valueAt(i);
- patches[patchesWritten] = patch->mPatch;
- patches[patchesWritten++].id = patch->mHandle;
+ *num_patches = 0;
+ for (size_t patchIndex = 0; patchIndex < size(); patchIndex++) {
+ // do not report patches with AUDIO_DEVICE_IN_STUB as source or
+ // AUDIO_DEVICE_OUT_STUB as sink as those devices are used by stub HALs by convention
+ const sp<AudioPatch> patch = valueAt(patchIndex);
+ bool skip = false;
+ for (size_t srcIndex = 0; srcIndex < patch->mPatch.num_sources && !skip; srcIndex++) {
+ if (patch->mPatch.sources[srcIndex].type == AUDIO_PORT_TYPE_DEVICE &&
+ patch->mPatch.sources[srcIndex].ext.device.type == AUDIO_DEVICE_IN_STUB) {
+ skip = true;
+ }
+ }
+ for (size_t sinkIndex = 0; sinkIndex < patch->mPatch.num_sinks && !skip; sinkIndex++) {
+ if (patch->mPatch.sinks[sinkIndex].type == AUDIO_PORT_TYPE_DEVICE &&
+ patch->mPatch.sinks[sinkIndex].ext.device.type == AUDIO_DEVICE_OUT_STUB) {
+ skip = true;
+ }
+ }
+ if (skip) {
+ continue; // to next audio patch
+ }
+ if (patchesWritten < patchesMax) {
+ patches[patchesWritten] = patch->mPatch;
+ patches[patchesWritten++].id = patch->mHandle;
+ }
+ (*num_patches)++;
ALOGV("listAudioPatches() patch %zu num_sources %d num_sinks %d",
- i, patch->mPatch.num_sources, patch->mPatch.num_sinks);
+ patchIndex, patch->mPatch.num_sources, patch->mPatch.num_sinks);
}
- *num_patches = size();
ALOGV("listAudioPatches() got %zu patches needed %d", patchesWritten, *num_patches);
return NO_ERROR;
diff --git a/services/audiopolicy/common/managerdefinitions/src/StreamDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/StreamDescriptor.cpp
index 8388a50..359e473 100644
--- a/services/audiopolicy/common/managerdefinitions/src/StreamDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/StreamDescriptor.cpp
@@ -39,15 +39,15 @@
// Initialize the current stream's index to mIndexMax so volume isn't 0 in
// cases where the Java layer doesn't call into the audio policy service to
// set the default volume.
- mIndexCur.add(AUDIO_DEVICE_OUT_DEFAULT, mIndexMax);
+ mIndexCur.add(AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME, mIndexMax);
}
int StreamDescriptor::getVolumeIndex(audio_devices_t device) const
{
device = Volume::getDeviceForVolume(device);
- // there is always a valid entry for AUDIO_DEVICE_OUT_DEFAULT
+ // there is always a valid entry for AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME
if (mIndexCur.indexOfKey(device) < 0) {
- device = AUDIO_DEVICE_OUT_DEFAULT;
+ device = AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME;
}
return mIndexCur.valueFor(device);
}
diff --git a/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp b/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
index c6ed53e..f639551 100644
--- a/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
@@ -51,6 +51,7 @@
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_AUX_LINE),
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_IP),
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BUS),
+ MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_STUB),
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_AMBIENT),
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BUILTIN_MIC),
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET),
@@ -74,6 +75,7 @@
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_LOOPBACK),
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_IP),
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BUS),
+ MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_STUB),
};
template<>
diff --git a/services/audiopolicy/config/audio_policy_configuration_stub.xml b/services/audiopolicy/config/audio_policy_configuration_stub.xml
new file mode 100644
index 0000000..a7747f8
--- /dev/null
+++ b/services/audiopolicy/config/audio_policy_configuration_stub.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- Copyright (C) 2016 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.
+-->
+
+<audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <modules>
+ <module name="stub" halVersion="2.0">
+ <attachedDevices>
+ <item>Default Out</item>
+ <item>Default In</item>
+ </attachedDevices>
+ <defaultOutputDevice>Default Out</defaultOutputDevice>
+ <mixPorts>
+ <mixPort name="stub output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+
+ <mixPort name="stub input" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
+ </mixPort>
+ </mixPorts>
+ <devicePorts>
+ <devicePort tagName="Default Out" type="AUDIO_DEVICE_OUT_STUB" role="sink">
+ </devicePort>
+
+ <devicePort tagName="Default In" type="AUDIO_DEVICE_IN_STUB" role="source">
+ </devicePort>
+ </devicePorts>
+ <routes>
+ <route type="mix" sink="Default Out" sources="stub output"/>
+
+ <route type="mix" sink="stub input" sources="Default In"/>
+ </routes>
+
+ </module>
+
+ <!-- Remote Submix Audio HAL -->
+ <xi:include href="r_submix_audio_policy_configuration.xml"/>
+
+ </modules>
+
+ <xi:include href="audio_policy_volumes.xml"/>
+ <xi:include href="default_volume_tables.xml"/>
+
+</audioPolicyConfiguration>
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index f2224fd..d31429c 100755
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -254,10 +254,6 @@
case STRATEGY_TRANSMITTED_THROUGH_SPEAKER:
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
- if (!device) {
- ALOGE("getDeviceForStrategy() no device found for "\
- "STRATEGY_TRANSMITTED_THROUGH_SPEAKER");
- }
break;
case STRATEGY_SONIFICATION_RESPECTFUL:
@@ -373,11 +369,6 @@
if (device) break;
}
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_EARPIECE;
- if (device) break;
- device = mApmObserver->getDefaultOutputDevice()->type();
- if (device == AUDIO_DEVICE_NONE) {
- ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE");
- }
break;
case AUDIO_POLICY_FORCE_SPEAKER:
@@ -402,11 +393,6 @@
if (device) break;
}
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
- if (device) break;
- device = mApmObserver->getDefaultOutputDevice()->type();
- if (device == AUDIO_DEVICE_NONE) {
- ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE, FORCE_SPEAKER");
- }
break;
}
break;
@@ -431,9 +417,6 @@
if ((strategy == STRATEGY_SONIFICATION) ||
(mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)) {
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
- if (device == AUDIO_DEVICE_NONE) {
- ALOGE("getDeviceForStrategy() speaker device not found for STRATEGY_SONIFICATION");
- }
}
// The second device used for sonification is the same as the device used by media strategy
// FALL THROUGH
@@ -545,12 +528,6 @@
AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED)) {
device &= ~AUDIO_DEVICE_OUT_SPEAKER;
}
-
- if (device) break;
- device = mApmObserver->getDefaultOutputDevice()->type();
- if (device == AUDIO_DEVICE_NONE) {
- ALOGE("getDeviceForStrategy() no device found for STRATEGY_MEDIA");
- }
} break;
default:
@@ -558,6 +535,12 @@
break;
}
+ if (device == AUDIO_DEVICE_NONE) {
+ ALOGV("getDeviceForStrategy() no device found for strategy %d", strategy);
+ device = mApmObserver->getDefaultOutputDevice()->type();
+ ALOGE_IF(device == AUDIO_DEVICE_NONE,
+ "getDeviceForStrategy() no default device defined");
+ }
ALOGVV("getDeviceForStrategy() strategy %d, device %x", strategy, device);
return device;
}
@@ -677,6 +660,14 @@
ALOGW("getDeviceForInputSource() invalid input source %d", inputSource);
break;
}
+ if (device == AUDIO_DEVICE_NONE) {
+ ALOGV("getDeviceForInputSource() no device found for source %d", inputSource);
+ if (availableDeviceTypes & AUDIO_DEVICE_IN_STUB) {
+ device = AUDIO_DEVICE_IN_STUB;
+ }
+ ALOGE_IF(device == AUDIO_DEVICE_NONE,
+ "getDeviceForInputSource() no default device defined");
+ }
ALOGV("getDeviceForInputSource()input source %d, device %08x", inputSource, device);
return device;
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index fac2342..29ab262 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1847,8 +1847,8 @@
// the requested device
// - For non default requested device, currently selected device on the output is either the
// requested device or one of the devices selected by the strategy
- // - For default requested device (AUDIO_DEVICE_OUT_DEFAULT), apply volume only if no specific
- // device volume value exists for currently selected device.
+ // - For default requested device (AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME), apply volume only if
+ // no specific device volume value exists for currently selected device.
status_t status = NO_ERROR;
for (size_t i = 0; i < mOutputs.size(); i++) {
sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
@@ -1866,7 +1866,7 @@
continue;
}
bool applyDefault = false;
- if (device != AUDIO_DEVICE_OUT_DEFAULT) {
+ if (device != AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) {
curStreamDevice |= device;
} else if (!mVolumeCurves->hasVolumeIndexForDevice(
stream, Volume::getDeviceForVolume(curStreamDevice))) {
@@ -1895,9 +1895,9 @@
if (!audio_is_output_device(device)) {
return BAD_VALUE;
}
- // if device is AUDIO_DEVICE_OUT_DEFAULT, return volume for device corresponding to
+ // if device is AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME, return volume for device corresponding to
// the strategy the stream belongs to.
- if (device == AUDIO_DEVICE_OUT_DEFAULT) {
+ if (device == AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) {
device = getDeviceForStrategy(getStrategy(stream), true /*fromCache*/);
}
device = Volume::getDeviceForVolume(device);
@@ -2331,19 +2331,29 @@
size_t portsMax = *num_ports;
*num_ports = 0;
if (type == AUDIO_PORT_TYPE_NONE || type == AUDIO_PORT_TYPE_DEVICE) {
+ // do not report devices with type AUDIO_DEVICE_IN_STUB or AUDIO_DEVICE_OUT_STUB
+ // as they are used by stub HALs by convention
if (role == AUDIO_PORT_ROLE_SINK || role == AUDIO_PORT_ROLE_NONE) {
- for (size_t i = 0;
- i < mAvailableOutputDevices.size() && portsWritten < portsMax; i++) {
- mAvailableOutputDevices[i]->toAudioPort(&ports[portsWritten++]);
+ for (size_t i = 0; i < mAvailableOutputDevices.size(); i++) {
+ if (mAvailableOutputDevices[i]->type() == AUDIO_DEVICE_OUT_STUB) {
+ continue;
+ }
+ if (portsWritten < portsMax) {
+ mAvailableOutputDevices[i]->toAudioPort(&ports[portsWritten++]);
+ }
+ (*num_ports)++;
}
- *num_ports += mAvailableOutputDevices.size();
}
if (role == AUDIO_PORT_ROLE_SOURCE || role == AUDIO_PORT_ROLE_NONE) {
- for (size_t i = 0;
- i < mAvailableInputDevices.size() && portsWritten < portsMax; i++) {
- mAvailableInputDevices[i]->toAudioPort(&ports[portsWritten++]);
+ for (size_t i = 0; i < mAvailableInputDevices.size(); i++) {
+ if (mAvailableInputDevices[i]->type() == AUDIO_DEVICE_IN_STUB) {
+ continue;
+ }
+ if (portsWritten < portsMax) {
+ mAvailableInputDevices[i]->toAudioPort(&ports[portsWritten++]);
+ }
+ (*num_ports)++;
}
- *num_ports += mAvailableInputDevices.size();
}
}
if (type == AUDIO_PORT_TYPE_NONE || type == AUDIO_PORT_TYPE_MIX) {