Merge "Refactor opening output interface between AF and AP."
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index 32904bb..ad79e9c 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -1,7 +1,15 @@
cc_library_headers {
name: "libaudioclient_headers",
vendor_available: true,
- export_include_dirs: ["include"],
+ header_libs: [
+ "libaudiofoundation_headers",
+ ],
+ export_include_dirs: [
+ "include",
+ ],
+ export_header_lib_headers: [
+ "libaudiofoundation_headers",
+ ],
}
cc_library_shared {
@@ -63,6 +71,7 @@
"TrackPlayerBase.cpp",
],
shared_libs: [
+ "libaudiofoundation",
"libaudioutils",
"libaudiopolicy",
"libaudiomanager",
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index 46cfb68..6e9a7cf 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -392,20 +392,18 @@
virtual status_t openOutput(audio_module_handle_t module,
audio_io_handle_t *output,
audio_config_t *config,
- audio_devices_t *devices,
- const String8& address,
+ const sp<DeviceDescriptorBase>& device,
uint32_t *latencyMs,
audio_output_flags_t flags)
{
- if (output == NULL || config == NULL || devices == NULL || latencyMs == NULL) {
+ if (output == nullptr || config == nullptr || device == nullptr || latencyMs == nullptr) {
return BAD_VALUE;
}
Parcel data, reply;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
data.writeInt32(module);
data.write(config, sizeof(audio_config_t));
- data.writeInt32(*devices);
- data.writeString8(address);
+ data.writeParcelable(*device);
data.writeInt32((int32_t) flags);
status_t status = remote()->transact(OPEN_OUTPUT, data, &reply);
if (status != NO_ERROR) {
@@ -420,7 +418,6 @@
*output = (audio_io_handle_t)reply.readInt32();
ALOGV("openOutput() returned output, %d", *output);
reply.read(config, sizeof(audio_config_t));
- *devices = (audio_devices_t)reply.readInt32();
*latencyMs = reply.readInt32();
return NO_ERROR;
}
@@ -1198,19 +1195,21 @@
if (data.read(&config, sizeof(audio_config_t)) != NO_ERROR) {
ALOGE("b/23905951");
}
- audio_devices_t devices = (audio_devices_t)data.readInt32();
- String8 address(data.readString8());
+ sp<DeviceDescriptorBase> device = new DeviceDescriptorBase(AUDIO_DEVICE_NONE);
+ status_t status = NO_ERROR;
+ if ((status = data.readParcelable(device.get())) != NO_ERROR) {
+ reply->writeInt32((int32_t)status);
+ return NO_ERROR;
+ }
audio_output_flags_t flags = (audio_output_flags_t) data.readInt32();
uint32_t latencyMs = 0;
audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
- status_t status = openOutput(module, &output, &config,
- &devices, address, &latencyMs, flags);
+ status = openOutput(module, &output, &config, device, &latencyMs, flags);
ALOGV("OPEN_OUTPUT output, %d", output);
reply->writeInt32((int32_t)status);
if (status == NO_ERROR) {
reply->writeInt32((int32_t)output);
reply->write(&config, sizeof(audio_config_t));
- reply->writeInt32(devices);
reply->writeInt32(latencyMs);
}
return NO_ERROR;
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index b580a88..0a65857 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -27,6 +27,7 @@
#include <binder/Parcel.h>
#include <binder/Parcelable.h>
#include <media/AudioClient.h>
+#include <media/DeviceDescriptorBase.h>
#include <media/IAudioTrack.h>
#include <media/IAudioFlingerClient.h>
#include <system/audio.h>
@@ -416,8 +417,7 @@
virtual status_t openOutput(audio_module_handle_t module,
audio_io_handle_t *output,
audio_config_t *config,
- audio_devices_t *devices,
- const String8& address,
+ const sp<DeviceDescriptorBase>& device,
uint32_t *latencyMs,
audio_output_flags_t flags) = 0;
virtual audio_io_handle_t openDuplicateOutput(audio_io_handle_t output1,
diff --git a/media/libaudiofoundation/Android.bp b/media/libaudiofoundation/Android.bp
index 1df0d16..edc06d2 100644
--- a/media/libaudiofoundation/Android.bp
+++ b/media/libaudiofoundation/Android.bp
@@ -15,6 +15,7 @@
cc_library {
name: "libaudiofoundation",
vendor_available: true,
+ double_loadable: true,
srcs: [
"AudioContainers.cpp",
diff --git a/media/libaudiofoundation/include/media/AudioContainers.h b/media/libaudiofoundation/include/media/AudioContainers.h
index 8347c71..05e68fa 100644
--- a/media/libaudiofoundation/include/media/AudioContainers.h
+++ b/media/libaudiofoundation/include/media/AudioContainers.h
@@ -17,6 +17,7 @@
#pragma once
#include <algorithm>
+#include <functional>
#include <iterator>
#include <set>
#include <vector>
@@ -78,6 +79,11 @@
return deviceTypes.size() == 1 && p(*(deviceTypes.begin()));
}
+static inline bool areAllOfSameDeviceType(const DeviceTypeSet& deviceTypes,
+ std::function<bool(audio_devices_t)> p) {
+ return std::all_of(deviceTypes.begin(), deviceTypes.end(), p);
+}
+
static inline void resetDeviceTypes(DeviceTypeSet& deviceTypes, audio_devices_t typeToAdd) {
deviceTypes.clear();
deviceTypes.insert(typeToAdd);
diff --git a/media/libaudiohal/impl/DeviceHalHidl.cpp b/media/libaudiohal/impl/DeviceHalHidl.cpp
index b07f21d..3d3a5eb 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalHidl.cpp
@@ -229,14 +229,14 @@
status_t DeviceHalHidl::openOutputStream(
audio_io_handle_t handle,
- audio_devices_t devices,
+ audio_devices_t deviceType,
audio_output_flags_t flags,
struct audio_config *config,
const char *address,
sp<StreamOutHalInterface> *outStream) {
if (mDevice == 0) return NO_INIT;
DeviceAddress hidlDevice;
- status_t status = deviceAddressFromHal(devices, address, &hidlDevice);
+ status_t status = deviceAddressFromHal(deviceType, address, &hidlDevice);
if (status != OK) return status;
AudioConfig hidlConfig;
HidlUtils::audioConfigFromHal(*config, &hidlConfig);
diff --git a/media/libaudiohal/impl/DeviceHalLocal.cpp b/media/libaudiohal/impl/DeviceHalLocal.cpp
index ee68252..dfbb6b2 100644
--- a/media/libaudiohal/impl/DeviceHalLocal.cpp
+++ b/media/libaudiohal/impl/DeviceHalLocal.cpp
@@ -104,7 +104,7 @@
status_t DeviceHalLocal::openOutputStream(
audio_io_handle_t handle,
- audio_devices_t devices,
+ audio_devices_t deviceType,
audio_output_flags_t flags,
struct audio_config *config,
const char *address,
@@ -112,11 +112,11 @@
audio_stream_out_t *halStream;
ALOGV("open_output_stream handle: %d devices: %x flags: %#x"
"srate: %d format %#x channels %x address %s",
- handle, devices, flags,
+ handle, deviceType, flags,
config->sample_rate, config->format, config->channel_mask,
address);
int openResut = mDev->open_output_stream(
- mDev, handle, devices, flags, config, &halStream, address);
+ mDev, handle, deviceType, flags, config, &halStream, address);
if (openResut == OK) {
*outStream = new StreamOutHalLocal(halStream, this);
}
diff --git a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
index e565237..2200a7f 100644
--- a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
@@ -69,7 +69,7 @@
// by releasing all references to the returned object.
virtual status_t openOutputStream(
audio_io_handle_t handle,
- audio_devices_t devices,
+ audio_devices_t deviceType,
audio_output_flags_t flags,
struct audio_config *config,
const char *address,
diff --git a/services/audioflinger/Android.bp b/services/audioflinger/Android.bp
index d50a556..de8c7e7 100644
--- a/services/audioflinger/Android.bp
+++ b/services/audioflinger/Android.bp
@@ -34,6 +34,7 @@
],
shared_libs: [
+ "libaudiofoundation",
"libaudiohal",
"libaudioprocessing",
"libaudiospdif",
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 65261da..eba0b20 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -381,7 +381,7 @@
AudioHwDevice* AudioFlinger::findSuitableHwDev_l(
audio_module_handle_t module,
- audio_devices_t devices)
+ audio_devices_t deviceType)
{
// if module is 0, the request comes from an old policy manager and we should load
// well known modules
@@ -396,7 +396,7 @@
sp<DeviceHalInterface> dev = audioHwDevice->hwDevice();
uint32_t supportedDevices;
if (dev->getSupportedDevices(&supportedDevices) == OK &&
- (supportedDevices & devices) == devices) {
+ (supportedDevices & deviceType) == deviceType) {
return audioHwDevice;
}
}
@@ -2304,13 +2304,13 @@
sp<AudioFlinger::ThreadBase> AudioFlinger::openOutput_l(audio_module_handle_t module,
- audio_io_handle_t *output,
- audio_config_t *config,
- audio_devices_t devices,
- const String8& address,
- audio_output_flags_t flags)
+ audio_io_handle_t *output,
+ audio_config_t *config,
+ audio_devices_t deviceType,
+ const String8& address,
+ audio_output_flags_t flags)
{
- AudioHwDevice *outHwDev = findSuitableHwDev_l(module, devices);
+ AudioHwDevice *outHwDev = findSuitableHwDev_l(module, deviceType);
if (outHwDev == NULL) {
return 0;
}
@@ -2351,7 +2351,7 @@
status_t status = outHwDev->openOutputStream(
&outputStream,
*output,
- devices,
+ deviceType,
flags,
config,
address.string());
@@ -2362,7 +2362,7 @@
if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
sp<MmapPlaybackThread> thread =
new MmapPlaybackThread(this, *output, outHwDev, outputStream,
- devices, AUDIO_DEVICE_NONE, mSystemReady);
+ deviceType, AUDIO_DEVICE_NONE, mSystemReady);
mMmapThreads.add(*output, thread);
ALOGV("openOutput_l() created mmap playback thread: ID %d thread %p",
*output, thread.get());
@@ -2370,17 +2370,18 @@
} else {
sp<PlaybackThread> thread;
if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
- thread = new OffloadThread(this, outputStream, *output, devices, mSystemReady);
+ thread = new OffloadThread(this, outputStream, *output, deviceType, mSystemReady);
ALOGV("openOutput_l() created offload output: ID %d thread %p",
*output, thread.get());
} else if ((flags & AUDIO_OUTPUT_FLAG_DIRECT)
|| !isValidPcmSinkFormat(config->format)
|| !isValidPcmSinkChannelMask(config->channel_mask)) {
- thread = new DirectOutputThread(this, outputStream, *output, devices, mSystemReady);
+ thread = new DirectOutputThread(
+ this, outputStream, *output, deviceType, mSystemReady);
ALOGV("openOutput_l() created direct output: ID %d thread %p",
*output, thread.get());
} else {
- thread = new MixerThread(this, outputStream, *output, devices, mSystemReady);
+ thread = new MixerThread(this, outputStream, *output, deviceType, mSystemReady);
ALOGV("openOutput_l() created mixer output: ID %d thread %p",
*output, thread.get());
}
@@ -2396,27 +2397,29 @@
status_t AudioFlinger::openOutput(audio_module_handle_t module,
audio_io_handle_t *output,
audio_config_t *config,
- audio_devices_t *devices,
- const String8& address,
+ const sp<DeviceDescriptorBase>& device,
uint32_t *latencyMs,
audio_output_flags_t flags)
{
- ALOGI("openOutput() this %p, module %d Device %#x, SamplingRate %d, Format %#08x, "
+ ALOGI("openOutput() this %p, module %d Device %s, SamplingRate %d, Format %#08x, "
"Channels %#x, flags %#x",
this, module,
- (devices != NULL) ? *devices : 0,
+ device->toString().c_str(),
config->sample_rate,
config->format,
config->channel_mask,
flags);
- if (devices == NULL || *devices == AUDIO_DEVICE_NONE) {
+ audio_devices_t deviceType = device->type();
+ const String8 address = String8(device->address().c_str());
+
+ if (deviceType == AUDIO_DEVICE_NONE) {
return BAD_VALUE;
}
Mutex::Autolock _l(mLock);
- sp<ThreadBase> thread = openOutput_l(module, output, config, *devices, address, flags);
+ sp<ThreadBase> thread = openOutput_l(module, output, config, deviceType, address, flags);
if (thread != 0) {
if ((flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0) {
PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index d2de5fe..65be06d 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -175,8 +175,7 @@
virtual status_t openOutput(audio_module_handle_t module,
audio_io_handle_t *output,
audio_config_t *config,
- audio_devices_t *devices,
- const String8& address,
+ const sp<DeviceDescriptorBase>& device,
uint32_t *latencyMs,
audio_output_flags_t flags);
@@ -372,7 +371,7 @@
virtual void onFirstRef();
AudioHwDevice* findSuitableHwDev_l(audio_module_handle_t module,
- audio_devices_t devices);
+ audio_devices_t deviceType);
// Set kEnableExtendedChannels to true to enable greater than stereo output
// for the MixerThread and device sink. Number of channels allowed is
@@ -678,11 +677,11 @@
audio_devices_t outputDevice,
const String8& outputDeviceAddress);
sp<ThreadBase> openOutput_l(audio_module_handle_t module,
- audio_io_handle_t *output,
- audio_config_t *config,
- audio_devices_t devices,
- const String8& address,
- audio_output_flags_t flags);
+ audio_io_handle_t *output,
+ audio_config_t *config,
+ audio_devices_t deviceType,
+ const String8& address,
+ audio_output_flags_t flags);
void closeOutputFinish(const sp<PlaybackThread>& thread);
void closeInputFinish(const sp<RecordThread>& thread);
diff --git a/services/audioflinger/AudioHwDevice.cpp b/services/audioflinger/AudioHwDevice.cpp
index b109d06..dda164c 100644
--- a/services/audioflinger/AudioHwDevice.cpp
+++ b/services/audioflinger/AudioHwDevice.cpp
@@ -34,7 +34,7 @@
status_t AudioHwDevice::openOutputStream(
AudioStreamOut **ppStreamOut,
audio_io_handle_t handle,
- audio_devices_t devices,
+ audio_devices_t deviceType,
audio_output_flags_t flags,
struct audio_config *config,
const char *address)
@@ -50,7 +50,7 @@
config->sample_rate,
config->format,
config->channel_mask);
- status_t status = outputStream->open(handle, devices, config, address);
+ status_t status = outputStream->open(handle, deviceType, config, address);
if (status != NO_ERROR) {
delete outputStream;
@@ -75,7 +75,7 @@
if (wrapperNeeded) {
if (SPDIFEncoder::isFormatSupported(originalConfig.format)) {
outputStream = new SpdifStreamOut(this, flags, originalConfig.format);
- status = outputStream->open(handle, devices, &originalConfig, address);
+ status = outputStream->open(handle, deviceType, &originalConfig, address);
if (status != NO_ERROR) {
ALOGE("ERROR - openOutputStream(), SPDIF open returned %d",
status);
diff --git a/services/audioflinger/AudioHwDevice.h b/services/audioflinger/AudioHwDevice.h
index d4299b0..6709d17 100644
--- a/services/audioflinger/AudioHwDevice.h
+++ b/services/audioflinger/AudioHwDevice.h
@@ -76,7 +76,7 @@
status_t openOutputStream(
AudioStreamOut **ppStreamOut,
audio_io_handle_t handle,
- audio_devices_t devices,
+ audio_devices_t deviceType,
audio_output_flags_t flags,
struct audio_config *config,
const char *address);
diff --git a/services/audioflinger/AudioStreamOut.cpp b/services/audioflinger/AudioStreamOut.cpp
index a60a5f2..d13cb8f 100644
--- a/services/audioflinger/AudioStreamOut.cpp
+++ b/services/audioflinger/AudioStreamOut.cpp
@@ -118,7 +118,7 @@
status_t AudioStreamOut::open(
audio_io_handle_t handle,
- audio_devices_t devices,
+ audio_devices_t deviceType,
struct audio_config *config,
const char *address)
{
@@ -130,7 +130,7 @@
int status = hwDev()->openOutputStream(
handle,
- devices,
+ deviceType,
customFlags,
config,
address,
@@ -152,7 +152,7 @@
status = hwDev()->openOutputStream(
handle,
- devices,
+ deviceType,
customFlags,
&customConfig,
address,
diff --git a/services/audioflinger/AudioStreamOut.h b/services/audioflinger/AudioStreamOut.h
index b16b1af..16fbcf2 100644
--- a/services/audioflinger/AudioStreamOut.h
+++ b/services/audioflinger/AudioStreamOut.h
@@ -47,7 +47,7 @@
virtual status_t open(
audio_io_handle_t handle,
- audio_devices_t devices,
+ audio_devices_t deviceType,
struct audio_config *config,
const char *address);
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 35126ad..0d3e614 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -19,6 +19,7 @@
#include <media/AudioSystem.h>
#include <media/AudioPolicy.h>
+#include <media/DeviceDescriptorBase.h>
#include <utils/String8.h>
namespace android {
@@ -296,8 +297,7 @@
virtual status_t openOutput(audio_module_handle_t module,
audio_io_handle_t *output,
audio_config_t *config,
- audio_devices_t *devices,
- const String8& address,
+ const sp<DeviceDescriptorBase>& device,
uint32_t *latencyMs,
audio_output_flags_t flags) = 0;
// creates a special output that is duplicated to the two outputs passed as arguments. The duplication is performed by
diff --git a/services/audiopolicy/common/include/Volume.h b/services/audiopolicy/common/include/Volume.h
index c3a02f9..7c8ce83 100644
--- a/services/audiopolicy/common/include/Volume.h
+++ b/services/audiopolicy/common/include/Volume.h
@@ -22,6 +22,8 @@
#include <utils/Log.h>
#include <math.h>
+#include "policy.h"
+
namespace android {
/**
@@ -85,43 +87,14 @@
*/
static audio_devices_t getDeviceForVolume(const android::DeviceTypeSet& deviceTypes)
{
- audio_devices_t deviceType = AUDIO_DEVICE_NONE;
if (deviceTypes.empty()) {
// this happens when forcing a route update and no track is active on an output.
// In this case the returned category is not important.
- deviceType = AUDIO_DEVICE_OUT_SPEAKER;
- } else if (deviceTypes.size() > 1) {
- // Multiple device selection is either:
- // - speaker + one other device: give priority to speaker in this case.
- // - one A2DP device + another device: happens with duplicated output. In this case
- // retain the device on the A2DP output as the other must not correspond to an active
- // selection if not the speaker.
- // - HDMI-CEC system audio mode only output: give priority to available item in order.
- if (deviceTypes.count(AUDIO_DEVICE_OUT_SPEAKER) != 0) {
- deviceType = AUDIO_DEVICE_OUT_SPEAKER;
- } else if (deviceTypes.count(AUDIO_DEVICE_OUT_SPEAKER_SAFE) != 0) {
- deviceType = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
- } else if (deviceTypes.count(AUDIO_DEVICE_OUT_HDMI_ARC) != 0) {
- deviceType = AUDIO_DEVICE_OUT_HDMI_ARC;
- } else if (deviceTypes.count(AUDIO_DEVICE_OUT_AUX_LINE) != 0) {
- deviceType = AUDIO_DEVICE_OUT_AUX_LINE;
- } else if (deviceTypes.count(AUDIO_DEVICE_OUT_SPDIF) != 0) {
- deviceType = AUDIO_DEVICE_OUT_SPDIF;
- } else {
- std::vector<audio_devices_t> a2dpDevices = android::Intersection(
- deviceTypes, android::getAudioDeviceOutAllA2dpSet());
- if (a2dpDevices.size() > 1) {
- ALOGW("getDeviceForVolume() invalid device combination: %s",
- android::dumpDeviceTypes(deviceTypes).c_str());
- }
- if (!a2dpDevices.empty()) {
- deviceType = a2dpDevices[0];
- }
- }
- } else {
- deviceType = *(deviceTypes.begin());
+ return AUDIO_DEVICE_OUT_SPEAKER;
}
+ audio_devices_t deviceType = apm_extract_one_audio_device(deviceTypes);
+
/*SPEAKER_SAFE is an alias of SPEAKER for purposes of volume control*/
if (deviceType == AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
deviceType = AUDIO_DEVICE_OUT_SPEAKER;
diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h
index 630efc1..0537365 100644
--- a/services/audiopolicy/common/include/policy.h
+++ b/services/audiopolicy/common/include/policy.h
@@ -19,6 +19,8 @@
#include <system/audio.h>
#include <vector>
+#include <media/AudioContainers.h>
+
namespace android {
using StreamTypeVector = std::vector<audio_stream_type_t>;
@@ -199,3 +201,43 @@
{
return hasStream(streams, AUDIO_STREAM_VOICE_CALL);
}
+
+/**
+ * @brief extract one device relevant from multiple device selection
+ * @param deviceTypes collection of audio device type
+ * @return the device type that is selected
+ */
+static inline audio_devices_t apm_extract_one_audio_device(
+ const android::DeviceTypeSet& deviceTypes) {
+ if (deviceTypes.empty()) {
+ return AUDIO_DEVICE_NONE;
+ } else if (deviceTypes.size() == 1) {
+ return *(deviceTypes.begin());
+ } else {
+ // Multiple device selection is either:
+ // - speaker + one other device: give priority to speaker in this case.
+ // - one A2DP device + another device: happens with duplicated output. In this case
+ // retain the device on the A2DP output as the other must not correspond to an active
+ // selection if not the speaker.
+ // - HDMI-CEC system audio mode only output: give priority to available item in order.
+ if (deviceTypes.count(AUDIO_DEVICE_OUT_SPEAKER) != 0) {
+ return AUDIO_DEVICE_OUT_SPEAKER;
+ } else if (deviceTypes.count(AUDIO_DEVICE_OUT_SPEAKER_SAFE) != 0) {
+ return AUDIO_DEVICE_OUT_SPEAKER_SAFE;
+ } else if (deviceTypes.count(AUDIO_DEVICE_OUT_HDMI_ARC) != 0) {
+ return AUDIO_DEVICE_OUT_HDMI_ARC;
+ } else if (deviceTypes.count(AUDIO_DEVICE_OUT_AUX_LINE) != 0) {
+ return AUDIO_DEVICE_OUT_AUX_LINE;
+ } else if (deviceTypes.count(AUDIO_DEVICE_OUT_SPDIF) != 0) {
+ return AUDIO_DEVICE_OUT_SPDIF;
+ } else {
+ std::vector<audio_devices_t> a2dpDevices = android::Intersection(
+ deviceTypes, android::getAudioDeviceOutAllA2dpSet());
+ if (a2dpDevices.empty() || a2dpDevices.size() > 1) {
+ ALOGW("%s invalid device combination: %s",
+ __func__, android::dumpDeviceTypes(deviceTypes).c_str());
+ }
+ return a2dpDevices.empty() ? AUDIO_DEVICE_NONE : a2dpDevices[0];
+ }
+ }
+}
\ No newline at end of file
diff --git a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
index 158215d..7faf90e 100644
--- a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
@@ -130,6 +130,14 @@
DeviceVector getFirstDevicesFromTypes(std::vector<audio_devices_t> orderedTypes) const;
sp<DeviceDescriptor> getFirstExistingDevice(std::vector<audio_devices_t> orderedTypes) const;
+ // Return device descriptor that is used to open an input/output stream.
+ // Null pointer will be returned if
+ // 1) this collection is empty
+ // 2) the device descriptors are not the same category(input or output)
+ // 3) there are more than one device type for input case
+ // 4) the combination of all devices is invalid for selection
+ sp<DeviceDescriptor> getDeviceForOpening() const;
+
// If there are devices with the given type and the devices to add is not empty,
// remove all the devices with the given type and add all the devices to add.
void replaceDevicesByType(audio_devices_t typeToRemove, const DeviceVector &devicesToAdd);
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 4ff69ee..dd51658 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -467,8 +467,11 @@
audio_io_handle_t *output)
{
mDevices = devices;
- const String8& address = devices.getFirstValidAddress();
- DeviceTypeSet deviceTypes = devices.types();
+ sp<DeviceDescriptor> device = devices.getDeviceForOpening();
+ LOG_ALWAYS_FATAL_IF(device == nullptr,
+ "%s failed to get device descriptor for opening "
+ "with the requested devices, all device types: %s",
+ __func__, dumpDeviceTypes(devices.types()).c_str());
audio_config_t lConfig;
if (config == nullptr) {
@@ -500,25 +503,19 @@
ALOGV("opening output for device %s profile %p name %s",
mDevices.toString().c_str(), mProfile.get(), mProfile->getName().c_str());
- // FIXME: Stop using device types as bit mask when the interface updated.
- audio_devices_t deviceType = deviceTypesToBitMask(deviceTypes);
status_t status = mClientInterface->openOutput(mProfile->getModuleHandle(),
output,
&lConfig,
- &deviceType,
- address,
+ device,
&mLatency,
mFlags);
- deviceTypes = deviceTypesFromBitMask(deviceType);
- LOG_ALWAYS_FATAL_IF(mDevices.types() != deviceTypes,
- "%s openOutput returned device %s when given device %s",
- __FUNCTION__, dumpDeviceTypes(mDevices.types()).c_str(),
- dumpDeviceTypes(deviceTypes).c_str());
if (status == NO_ERROR) {
LOG_ALWAYS_FATAL_IF(*output == AUDIO_IO_HANDLE_NONE,
- "%s openOutput returned output handle %d for device %s",
- __FUNCTION__, *output, dumpDeviceTypes(deviceTypes).c_str());
+ "%s openOutput returned output handle %d for device %s, "
+ "selected device %s for opening",
+ __FUNCTION__, *output, devices.toString().c_str(),
+ device->toString().c_str());
mSamplingRate = lConfig.sample_rate;
mChannelMask = lConfig.channel_mask;
mFormat = lConfig.format;
diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index 4e8c01c..0587041 100644
--- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -328,6 +328,24 @@
return device;
}
+sp<DeviceDescriptor> DeviceVector::getDeviceForOpening() const
+{
+ if (isEmpty()) {
+ // Return nullptr if this collection is empty.
+ return nullptr;
+ } else if (areAllOfSameDeviceType(types(), audio_is_input_device)) {
+ // For input case, return the first one when there is only one device.
+ return size() > 1 ? nullptr : *begin();
+ } else if (areAllOfSameDeviceType(types(), audio_is_output_device)) {
+ // For output case, return the device descriptor according to apm strategy.
+ audio_devices_t deviceType = apm_extract_one_audio_device(types());
+ return deviceType == AUDIO_DEVICE_NONE ? nullptr :
+ getDevice(deviceType, String8(""), AUDIO_FORMAT_DEFAULT);
+ }
+ // Return null pointer if the devices are not all input/output device.
+ return nullptr;
+}
+
void DeviceVector::replaceDevicesByType(
audio_devices_t typeToRemove, const DeviceVector &devicesToAdd) {
DeviceVector devicesToRemove = getDevicesFromType(typeToRemove);
diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
index d51cc6e..6de0c80 100644
--- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
@@ -39,8 +39,7 @@
status_t AudioPolicyService::AudioPolicyClient::openOutput(audio_module_handle_t module,
audio_io_handle_t *output,
audio_config_t *config,
- audio_devices_t *devices,
- const String8& address,
+ const sp<DeviceDescriptorBase>& device,
uint32_t *latencyMs,
audio_output_flags_t flags)
{
@@ -49,7 +48,7 @@
ALOGW("%s: could not get AudioFlinger", __func__);
return PERMISSION_DENIED;
}
- return af->openOutput(module, output, config, devices, address, latencyMs, flags);
+ return af->openOutput(module, output, config, device, latencyMs, flags);
}
audio_io_handle_t AudioPolicyService::AudioPolicyClient::openDuplicateOutput(
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 939df2c..175fed4 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -622,8 +622,7 @@
virtual status_t openOutput(audio_module_handle_t module,
audio_io_handle_t *output,
audio_config_t *config,
- audio_devices_t *devices,
- const String8& address,
+ const sp<DeviceDescriptorBase>& device,
uint32_t *latencyMs,
audio_output_flags_t flags);
// creates a special output that is duplicated to the two outputs passed as arguments. The duplication is performed by
diff --git a/services/audiopolicy/tests/AudioPolicyManagerTestClient.h b/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
index afe6f20..c2a92d7 100644
--- a/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
+++ b/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
@@ -34,8 +34,7 @@
status_t openOutput(audio_module_handle_t module,
audio_io_handle_t *output,
audio_config_t * /*config*/,
- audio_devices_t * /*devices*/,
- const String8 & /*address*/,
+ const sp<DeviceDescriptorBase>& /*device*/,
uint32_t * /*latencyMs*/,
audio_output_flags_t /*flags*/) override {
if (module >= mNextModuleHandle) {
diff --git a/services/audiopolicy/tests/AudioPolicyTestClient.h b/services/audiopolicy/tests/AudioPolicyTestClient.h
index e4c64e5..b92a2e6 100644
--- a/services/audiopolicy/tests/AudioPolicyTestClient.h
+++ b/services/audiopolicy/tests/AudioPolicyTestClient.h
@@ -31,8 +31,7 @@
status_t openOutput(audio_module_handle_t /*module*/,
audio_io_handle_t* /*output*/,
audio_config_t* /*config*/,
- audio_devices_t* /*devices*/,
- const String8& /*address*/,
+ const sp<DeviceDescriptorBase>& /*device*/,
uint32_t* /*latencyMs*/,
audio_output_flags_t /*flags*/) override { return NO_INIT; }
audio_io_handle_t openDuplicateOutput(audio_io_handle_t /*output1*/,