Merge "Refactor audio device type in audio flinger."
diff --git a/media/libaudiofoundation/AudioContainers.cpp b/media/libaudiofoundation/AudioContainers.cpp
index adc5d40..1bfe3f9 100644
--- a/media/libaudiofoundation/AudioContainers.cpp
+++ b/media/libaudiofoundation/AudioContainers.cpp
@@ -50,6 +50,10 @@
}
bool deviceTypesToString(const DeviceTypeSet &deviceTypes, std::string &str) {
+ if (deviceTypes.empty()) {
+ str = "Empty device types";
+ return true;
+ }
bool ret = true;
for (auto it = deviceTypes.begin(); it != deviceTypes.end();) {
std::string deviceTypeStr;
@@ -83,4 +87,10 @@
return ret;
}
+std::string toString(const DeviceTypeSet& deviceTypes) {
+ std::string ret;
+ deviceTypesToString(deviceTypes, ret);
+ return ret;
+}
+
} // namespace android
diff --git a/media/libaudiofoundation/AudioDeviceTypeAddr.cpp b/media/libaudiofoundation/AudioDeviceTypeAddr.cpp
index 3e43ead..d390467 100644
--- a/media/libaudiofoundation/AudioDeviceTypeAddr.cpp
+++ b/media/libaudiofoundation/AudioDeviceTypeAddr.cpp
@@ -26,6 +26,11 @@
return mType == other.mType && mAddress == other.mAddress;
}
+void AudioDeviceTypeAddr::reset() {
+ mType = AUDIO_DEVICE_NONE;
+ mAddress = "";
+}
+
status_t AudioDeviceTypeAddr::readFromParcel(const Parcel *parcel) {
status_t status;
if ((status = parcel->readUint32(&mType)) != NO_ERROR) return status;
@@ -40,4 +45,13 @@
return status;
}
+
+DeviceTypeSet getAudioDeviceTypes(const AudioDeviceTypeAddrVector& deviceTypeAddrs) {
+ DeviceTypeSet deviceTypes;
+ for (const auto& deviceTypeAddr : deviceTypeAddrs) {
+ deviceTypes.insert(deviceTypeAddr.mType);
+ }
+ return deviceTypes;
+}
+
}
\ No newline at end of file
diff --git a/media/libaudiofoundation/DeviceDescriptorBase.cpp b/media/libaudiofoundation/DeviceDescriptorBase.cpp
index d99c2c0..ef7576e 100644
--- a/media/libaudiofoundation/DeviceDescriptorBase.cpp
+++ b/media/libaudiofoundation/DeviceDescriptorBase.cpp
@@ -147,4 +147,25 @@
return status;
}
+std::string toString(const DeviceDescriptorBaseVector& devices)
+{
+ std::string ret;
+ for (const auto& device : devices) {
+ if (device != *devices.begin()) {
+ ret += ";";
+ }
+ ret += device->toString();
+ }
+ return ret;
+}
+
+AudioDeviceTypeAddrVector deviceTypeAddrsFromDescriptors(const DeviceDescriptorBaseVector& devices)
+{
+ AudioDeviceTypeAddrVector deviceTypeAddrs;
+ for (const auto& device : devices) {
+ deviceTypeAddrs.push_back(device->getDeviceTypeAddr());
+ }
+ return deviceTypeAddrs;
+}
+
} // namespace android
diff --git a/media/libaudiofoundation/include/media/AudioContainers.h b/media/libaudiofoundation/include/media/AudioContainers.h
index 05e68fa..2a3385b 100644
--- a/media/libaudiofoundation/include/media/AudioContainers.h
+++ b/media/libaudiofoundation/include/media/AudioContainers.h
@@ -123,5 +123,10 @@
std::string dumpDeviceTypes(const DeviceTypeSet& deviceTypes);
+/**
+ * Return human readable string for device types.
+ */
+std::string toString(const DeviceTypeSet& deviceTypes);
+
} // namespace android
\ No newline at end of file
diff --git a/media/libaudiofoundation/include/media/AudioDeviceTypeAddr.h b/media/libaudiofoundation/include/media/AudioDeviceTypeAddr.h
index 392a355..5e5e762 100644
--- a/media/libaudiofoundation/include/media/AudioDeviceTypeAddr.h
+++ b/media/libaudiofoundation/include/media/AudioDeviceTypeAddr.h
@@ -17,9 +17,11 @@
#pragma once
#include <string>
+#include <vector>
#include <binder/Parcelable.h>
#include <binder/Parcel.h>
+#include <media/AudioContainers.h>
#include <system/audio.h>
#include <utils/Errors.h>
@@ -35,6 +37,8 @@
bool equals(const AudioDeviceTypeAddr& other) const;
+ void reset();
+
status_t readFromParcel(const Parcel *parcel) override;
status_t writeToParcel(Parcel *parcel) const override;
@@ -43,4 +47,11 @@
std::string mAddress;
};
+using AudioDeviceTypeAddrVector = std::vector<AudioDeviceTypeAddr>;
+
+/**
+ * Return a collection of audio device types from a collection of AudioDeviceTypeAddr
+ */
+DeviceTypeSet getAudioDeviceTypes(const AudioDeviceTypeAddrVector& deviceTypeAddrs);
+
}
diff --git a/media/libaudiofoundation/include/media/DeviceDescriptorBase.h b/media/libaudiofoundation/include/media/DeviceDescriptorBase.h
index 434533e..4c03667 100644
--- a/media/libaudiofoundation/include/media/DeviceDescriptorBase.h
+++ b/media/libaudiofoundation/include/media/DeviceDescriptorBase.h
@@ -16,8 +16,11 @@
#pragma once
+#include <vector>
+
#include <binder/Parcel.h>
#include <binder/Parcelable.h>
+#include <media/AudioContainers.h>
#include <media/AudioPort.h>
#include <media/AudioDeviceTypeAddr.h>
#include <utils/Errors.h>
@@ -66,4 +69,17 @@
AudioDeviceTypeAddr mDeviceTypeAddr;
};
+using DeviceDescriptorBaseVector = std::vector<sp<DeviceDescriptorBase>>;
+
+/**
+ * Return human readable string for collection of DeviceDescriptorBase.
+ * For a DeviceDescriptorBase, it contains port id, audio device type and address.
+ */
+std::string toString(const DeviceDescriptorBaseVector& devices);
+
+/**
+ * Return a set of device types and addresses from collection of DeviceDescriptorBase.
+ */
+AudioDeviceTypeAddrVector deviceTypeAddrsFromDescriptors(const DeviceDescriptorBaseVector& devices);
+
} // namespace android
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 9d80425..8429b98 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1357,6 +1357,13 @@
}
}
+void AudioFlinger::updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices)
+{
+ for (size_t i = 0; i < mRecordThreads.size(); i++) {
+ mRecordThreads.valueAt(i)->updateOutDevices(devices);
+ }
+}
+
// forwardAudioHwSyncToDownstreamPatches_l() must be called with AudioFlinger::mLock held
void AudioFlinger::forwardParametersToDownstreamPatches_l(
audio_io_handle_t upStream, const String8& keyValuePairs,
@@ -2361,8 +2368,7 @@
if (status == NO_ERROR) {
if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
sp<MmapPlaybackThread> thread =
- new MmapPlaybackThread(this, *output, outHwDev, outputStream,
- deviceType, AUDIO_DEVICE_NONE, mSystemReady);
+ new MmapPlaybackThread(this, *output, outHwDev, outputStream, mSystemReady);
mMmapThreads.add(*output, thread);
ALOGV("openOutput_l() created mmap playback thread: ID %d thread %p",
*output, thread.get());
@@ -2370,18 +2376,17 @@
} else {
sp<PlaybackThread> thread;
if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
- thread = new OffloadThread(this, outputStream, *output, deviceType, mSystemReady);
+ thread = new OffloadThread(this, outputStream, *output, 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, deviceType, mSystemReady);
+ thread = new DirectOutputThread(this, outputStream, *output, mSystemReady);
ALOGV("openOutput_l() created direct output: ID %d thread %p",
*output, thread.get());
} else {
- thread = new MixerThread(this, outputStream, *output, deviceType, mSystemReady);
+ thread = new MixerThread(this, outputStream, *output, mSystemReady);
ALOGV("openOutput_l() created mixer output: ID %d thread %p",
*output, thread.get());
}
@@ -2689,9 +2694,7 @@
AudioStreamIn *inputStream = new AudioStreamIn(inHwDev, inStream, flags);
if ((flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0) {
sp<MmapCaptureThread> thread =
- new MmapCaptureThread(this, *input,
- inHwDev, inputStream,
- primaryOutputDevice_l(), devices, mSystemReady);
+ new MmapCaptureThread(this, *input, inHwDev, inputStream, mSystemReady);
mMmapThreads.add(*input, thread);
ALOGV("openInput_l() created mmap capture thread: ID %d thread %p", *input,
thread.get());
@@ -2700,13 +2703,7 @@
// Start record thread
// RecordThread requires both input and output device indication to forward to audio
// pre processing modules
- sp<RecordThread> thread = new RecordThread(this,
- inputStream,
- *input,
- primaryOutputDevice_l(),
- devices,
- mSystemReady
- );
+ sp<RecordThread> thread = new RecordThread(this, inputStream, *input, mSystemReady);
mRecordThreads.add(*input, thread);
ALOGV("openInput_l() created record thread: ID %d thread %p", *input, thread.get());
return thread;
@@ -3122,15 +3119,15 @@
return NULL;
}
-audio_devices_t AudioFlinger::primaryOutputDevice_l() const
+DeviceTypeSet AudioFlinger::primaryOutputDevice_l() const
{
PlaybackThread *thread = primaryPlaybackThread_l();
if (thread == NULL) {
- return 0;
+ return DeviceTypeSet();
}
- return thread->outDevice();
+ return thread->outDeviceTypes();
}
AudioFlinger::PlaybackThread *AudioFlinger::fastPlaybackThread_l() const
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 65be06d..995b724 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -65,7 +65,10 @@
#include <media/audiohal/EffectBufferHalInterface.h>
#include <media/audiohal/StreamHalInterface.h>
#include <media/AudioBufferProvider.h>
+#include <media/AudioContainers.h>
+#include <media/AudioDeviceTypeAddr.h>
#include <media/AudioMixer.h>
+#include <media/DeviceDescriptorBase.h>
#include <media/ExtendedAudioBufferProvider.h>
#include <media/VolumeShaper.h>
@@ -716,7 +719,7 @@
// return thread associated with primary hardware device, or NULL
PlaybackThread *primaryPlaybackThread_l() const;
- audio_devices_t primaryOutputDevice_l() const;
+ DeviceTypeSet primaryOutputDevice_l() const;
// return the playback thread with smallest HAL buffer size, and prefer fast
PlaybackThread *fastPlaybackThread_l() const;
@@ -750,6 +753,7 @@
std::vector< sp<EffectModule> > purgeStaleEffects_l();
void broacastParametersToRecordThreads_l(const String8& keyValuePairs);
+ void updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices);
void forwardParametersToDownstreamPatches_l(
audio_io_handle_t upStream, const String8& keyValuePairs,
std::function<bool(const sp<PlaybackThread>&)> useThread = nullptr);
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index 18cb53b..cb1ef7f 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -25,6 +25,7 @@
#include "AudioFlinger.h"
#include <media/AudioParameter.h>
+#include <media/DeviceDescriptorBase.h>
#include <media/PatchBuilder.h>
#include <mediautils/ServiceUtilities.h>
@@ -351,7 +352,7 @@
goto exit;
}
// limit to connections between devices and output streams
- audio_devices_t type = AUDIO_DEVICE_NONE;
+ DeviceDescriptorBaseVector devices;
for (unsigned int i = 0; i < patch->num_sinks; i++) {
if (patch->sinks[i].type != AUDIO_PORT_TYPE_DEVICE) {
ALOGW("%s() invalid sink type %d for mix source",
@@ -364,7 +365,11 @@
status = BAD_VALUE;
goto exit;
}
- type |= patch->sinks[i].ext.device.type;
+ sp<DeviceDescriptorBase> device = new DeviceDescriptorBase(
+ patch->sinks[i].ext.device.type);
+ device->setAddress(patch->sinks[i].ext.device.address);
+ device->applyAudioPortConfig(&patch->sinks[i]);
+ devices.push_back(device);
}
sp<ThreadBase> thread =
mAudioFlinger.checkPlaybackThread_l(patch->sources[0].ext.mix.handle);
@@ -378,10 +383,7 @@
}
}
if (thread == mAudioFlinger.primaryPlaybackThread_l()) {
- AudioParameter param = AudioParameter();
- param.addInt(String8(AudioParameter::keyRouting), (int)type);
-
- mAudioFlinger.broacastParametersToRecordThreads_l(param.toString());
+ mAudioFlinger.updateOutDevicesForRecordThreads_l(devices);
}
status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle);
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 8704d16..bd031ea 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -29,6 +29,8 @@
#include <sys/stat.h>
#include <sys/syscall.h>
#include <cutils/properties.h>
+#include <media/AudioContainers.h>
+#include <media/AudioDeviceTypeAddr.h>
#include <media/AudioParameter.h>
#include <media/AudioResamplerPublic.h>
#include <media/RecordBufferConverter.h>
@@ -460,7 +462,7 @@
}
AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
- audio_devices_t outDevice, audio_devices_t inDevice, type_t type, bool systemReady)
+ type_t type, bool systemReady)
: Thread(false /*canCallJava*/),
mType(type),
mAudioFlinger(audioFlinger),
@@ -468,8 +470,7 @@
// are set by PlaybackThread::readOutputParameters_l() or
// RecordThread::readInputParameters_l()
//FIXME: mStandby should be true here. Is this some kind of hack?
- mStandby(false), mOutDevice(outDevice), mInDevice(inDevice),
- mPrevOutDevice(AUDIO_DEVICE_NONE), mPrevInDevice(AUDIO_DEVICE_NONE),
+ mStandby(false),
mAudioSource(AUDIO_SOURCE_DEFAULT), mId(id),
// mName will be set by concrete (non-virtual) subclass
mDeathRecipient(new PMDeathRecipient(this)),
@@ -646,6 +647,18 @@
return sendConfigEvent_l(configEvent);
}
+status_t AudioFlinger::ThreadBase::sendUpdateOutDeviceConfigEvent(
+ const DeviceDescriptorBaseVector& outDevices)
+{
+ if (type() != RECORD) {
+ // The update out device operation is only for record thread.
+ return INVALID_OPERATION;
+ }
+ Mutex::Autolock _l(mLock);
+ sp<ConfigEvent> configEvent = (ConfigEvent *)new UpdateOutDevicesConfigEvent(outDevices);
+ return sendConfigEvent_l(configEvent);
+}
+
// post condition: mConfigEvents.isEmpty()
void AudioFlinger::ThreadBase::processConfigEvents_l()
@@ -680,24 +693,29 @@
}
} break;
case CFG_EVENT_CREATE_AUDIO_PATCH: {
- const audio_devices_t oldDevice = getDevice();
+ const DeviceTypeSet oldDevices = getDeviceTypes();
CreateAudioPatchConfigEventData *data =
(CreateAudioPatchConfigEventData *)event->mData.get();
event->mStatus = createAudioPatch_l(&data->mPatch, &data->mHandle);
- const audio_devices_t newDevice = getDevice();
- mLocalLog.log("CFG_EVENT_CREATE_AUDIO_PATCH: old device %#x (%s) new device %#x (%s)",
- (unsigned)oldDevice, toString(oldDevice).c_str(),
- (unsigned)newDevice, toString(newDevice).c_str());
+ const DeviceTypeSet newDevices = getDeviceTypes();
+ mLocalLog.log("CFG_EVENT_CREATE_AUDIO_PATCH: old device %s (%s) new device %s (%s)",
+ dumpDeviceTypes(oldDevices).c_str(), toString(oldDevices).c_str(),
+ dumpDeviceTypes(newDevices).c_str(), toString(newDevices).c_str());
} break;
case CFG_EVENT_RELEASE_AUDIO_PATCH: {
- const audio_devices_t oldDevice = getDevice();
+ const DeviceTypeSet oldDevices = getDeviceTypes();
ReleaseAudioPatchConfigEventData *data =
(ReleaseAudioPatchConfigEventData *)event->mData.get();
event->mStatus = releaseAudioPatch_l(data->mHandle);
- const audio_devices_t newDevice = getDevice();
- mLocalLog.log("CFG_EVENT_RELEASE_AUDIO_PATCH: old device %#x (%s) new device %#x (%s)",
- (unsigned)oldDevice, toString(oldDevice).c_str(),
- (unsigned)newDevice, toString(newDevice).c_str());
+ const DeviceTypeSet newDevices = getDeviceTypes();
+ mLocalLog.log("CFG_EVENT_RELEASE_AUDIO_PATCH: old device %s (%s) new device %s (%s)",
+ dumpDeviceTypes(oldDevices).c_str(), toString(oldDevices).c_str(),
+ dumpDeviceTypes(newDevices).c_str(), toString(newDevices).c_str());
+ } break;
+ case CFG_EVENT_UPDATE_OUT_DEVICE: {
+ UpdateOutDevicesConfigEventData *data =
+ (UpdateOutDevicesConfigEventData *)event->mData.get();
+ updateOutDevices(data->mOutDevices);
} break;
default:
ALOG_ASSERT(false, "processConfigEvents_l() unknown event type %d", event->mType);
@@ -840,8 +858,10 @@
dprintf(fd, " none\n");
}
// Note: output device may be used by capture threads for effects such as AEC.
- dprintf(fd, " Output device: %#x (%s)\n", mOutDevice, toString(mOutDevice).c_str());
- dprintf(fd, " Input device: %#x (%s)\n", mInDevice, toString(mInDevice).c_str());
+ dprintf(fd, " Output devices: %s (%s)\n",
+ dumpDeviceTypes(outDeviceTypes()).c_str(), toString(outDeviceTypes()).c_str());
+ dprintf(fd, " Input device: %#x (%s)\n",
+ inDeviceType(), toString(inDeviceType()).c_str());
dprintf(fd, " Audio source: %d (%s)\n", mAudioSource, toString(mAudioSource).c_str());
// Dump timestamp statistics for the Thread types that support it.
@@ -1011,6 +1031,12 @@
mPowerManager.clear();
}
+void AudioFlinger::ThreadBase::updateOutDevices(
+ const DeviceDescriptorBaseVector& outDevices __unused)
+{
+ ALOGE("%s should only be called in RecordThread", __func__);
+}
+
void AudioFlinger::ThreadBase::PMDeathRecipient::binderDied(const wp<IBinder>& who __unused)
{
sp<ThreadBase> thread = mThread.promote();
@@ -1351,8 +1377,9 @@
}
effectCreated = true;
- effect->setDevice(mOutDevice);
- effect->setDevice(mInDevice);
+ // FIXME: use vector of device and address when effect interface is ready.
+ effect->setDevice(deviceTypesToBitMask(outDeviceTypes()));
+ effect->setDevice(inDeviceType());
effect->setMode(mAudioFlinger->getMode());
effect->setAudioSource(mAudioSource);
}
@@ -1468,8 +1495,8 @@
return status;
}
- effect->setDevice(mOutDevice);
- effect->setDevice(mInDevice);
+ effect->setDevice(deviceTypesToBitMask(outDeviceTypes()));
+ effect->setDevice(inDeviceType());
effect->setMode(mAudioFlinger->getMode());
effect->setAudioSource(mAudioSource);
@@ -1702,8 +1729,8 @@
item->setInt64(MM_PREFIX "channelMask", (int64_t)mChannelMask);
item->setCString(MM_PREFIX "encoding", toString(mFormat).c_str());
item->setInt32(MM_PREFIX "frameCount", (int32_t)mFrameCount);
- item->setCString(MM_PREFIX "outDevice", toString(mOutDevice).c_str());
- item->setCString(MM_PREFIX "inDevice", toString(mInDevice).c_str());
+ item->setCString(MM_PREFIX "outDevice", toString(outDeviceTypes()).c_str());
+ item->setCString(MM_PREFIX "inDevice", toString(inDeviceType()).c_str());
// thread statistics
if (mIoJitterMs.getN() > 0) {
@@ -1734,10 +1761,9 @@
AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger,
AudioStreamOut* output,
audio_io_handle_t id,
- audio_devices_t device,
type_t type,
bool systemReady)
- : ThreadBase(audioFlinger, id, device, AUDIO_DEVICE_NONE, type, systemReady),
+ : ThreadBase(audioFlinger, id, type, systemReady),
mNormalFrameCount(0), mSinkBuffer(NULL),
mMixerBufferEnabled(AudioFlinger::kEnableExtendedPrecision),
mMixerBuffer(NULL),
@@ -1800,8 +1826,9 @@
// TODO: We may also match on address as well as device type for
// AUDIO_DEVICE_OUT_BUS, AUDIO_DEVICE_OUT_ALL_A2DP, AUDIO_DEVICE_OUT_REMOTE_SUBMIX
if (type == MIXER || type == DIRECT) {
- mTimestampCorrectedDevices = (audio_devices_t)property_get_int64(
- "audio.timestamp.corrected_output_devices",
+ // TODO: This property should be ensure that only contains one single device type.
+ mTimestampCorrectedDevice = (audio_devices_t)property_get_int64(
+ "audio.timestamp.corrected_output_device",
(int64_t)(mIsMsdDevice ? AUDIO_DEVICE_OUT_BUS // turn on by default for MSD
: AUDIO_DEVICE_NONE));
}
@@ -2891,7 +2918,7 @@
{
if (!mMasterMute) {
char value[PROPERTY_VALUE_MAX];
- if (mOutDevice == AUDIO_DEVICE_OUT_REMOTE_SUBMIX) {
+ if (isSingleDeviceType(outDeviceTypes(), AUDIO_DEVICE_OUT_REMOTE_SUBMIX)) {
ALOGD("ro.audio.silent will be ignored for threads on AUDIO_DEVICE_OUT_REMOTE_SUBMIX");
return;
}
@@ -3035,7 +3062,7 @@
// make sure standby delay is not too short when connected to an A2DP sink to avoid
// truncating audio when going to standby.
mStandbyDelayNs = AudioFlinger::mStandbyTimeInNsecs;
- if ((mOutDevice & AUDIO_DEVICE_OUT_ALL_A2DP) != 0) {
+ if (!Intersection(outDeviceTypes(), getAudioDeviceOutAllA2dpSet()).empty()) {
if (mStandbyDelayNs < kDefaultStandbyTimeInNsecs) {
mStandbyDelayNs = kDefaultStandbyTimeInNsecs;
}
@@ -3283,8 +3310,8 @@
// If the device is AUDIO_DEVICE_OUT_BUS, check for downstream latency.
//
- // Note: we access outDevice() outside of mLock.
- if (isMsdDevice() && (outDevice() & AUDIO_DEVICE_OUT_BUS) != 0) {
+ // Note: we access outDeviceTypes() outside of mLock.
+ if (isMsdDevice() && outDeviceTypes().count(AUDIO_DEVICE_OUT_BUS) != 0) {
// Here, we try for the AF lock, but do not block on it as the latency
// is more informational.
if (mAudioFlinger->mLock.tryLock() == NO_ERROR) {
@@ -3820,8 +3847,10 @@
if (diff > 0) {
// notify of throttle end on debug log
// but prevent spamming for bluetooth
- ALOGD_IF(!audio_is_a2dp_out_device(outDevice()) &&
- !audio_is_hearing_aid_out_device(outDevice()),
+ ALOGD_IF(!isSingleDeviceType(
+ outDeviceTypes(), audio_is_a2dp_out_device) &&
+ !isSingleDeviceType(
+ outDeviceTypes(), audio_is_hearing_aid_out_device),
"mixer(%p) throttle end: throttle time(%u)", this, diff);
mThreadThrottleEndMs = mThreadThrottleTimeMs;
}
@@ -4006,25 +4035,31 @@
// store new device and send to effects
audio_devices_t type = AUDIO_DEVICE_NONE;
+ AudioDeviceTypeAddrVector deviceTypeAddrs;
for (unsigned int i = 0; i < patch->num_sinks; i++) {
+ LOG_ALWAYS_FATAL_IF(popcount(patch->sinks[i].ext.device.type) > 1
+ && !mOutput->audioHwDev->supportsAudioPatches(),
+ "Enumerated device type(%#x) must not be used "
+ "as it does not support audio patches",
+ patch->sinks[i].ext.device.type);
type |= patch->sinks[i].ext.device.type;
+ deviceTypeAddrs.push_back(AudioDeviceTypeAddr(patch->sinks[i].ext.device.type,
+ patch->sinks[i].ext.device.address));
}
audio_port_handle_t sinkPortId = patch->sinks[0].id;
#ifdef ADD_BATTERY_DATA
// when changing the audio output device, call addBatteryData to notify
// the change
- if (mOutDevice != type) {
+ if (outDeviceTypes() != deviceTypes) {
uint32_t params = 0;
// check whether speaker is on
- if (type & AUDIO_DEVICE_OUT_SPEAKER) {
+ if (deviceTypes.count(AUDIO_DEVICE_OUT_SPEAKER) > 0) {
params |= IMediaPlayerService::kBatteryDataSpeakerOn;
}
- audio_devices_t deviceWithoutSpeaker
- = AUDIO_DEVICE_OUT_ALL & ~AUDIO_DEVICE_OUT_SPEAKER;
// check if any other device (except speaker) is on
- if (type & deviceWithoutSpeaker) {
+ if (!isSingleDeviceType(deviceTypes, AUDIO_DEVICE_OUT_SPEAKER)) {
params |= IMediaPlayerService::kBatteryDataOtherAudioDeviceOn;
}
@@ -4038,11 +4073,12 @@
mEffectChains[i]->setDevice_l(type);
}
- // mPrevOutDevice is the latest device set by createAudioPatch_l(). It is not set when
- // the thread is created so that the first patch creation triggers an ioConfigChanged callback
- bool configChanged = (mPrevOutDevice != type) || (mDeviceId != sinkPortId);
- mOutDevice = type;
+ // mPatch.num_sinks is not set when the thread is created so that
+ // the first patch creation triggers an ioConfigChanged callback
+ bool configChanged = (mPatch.num_sinks == 0) ||
+ (mPatch.sinks[0].id != sinkPortId);
mPatch = *patch;
+ mOutDeviceTypeAddrs = deviceTypeAddrs;
if (mOutput->audioHwDev->supportsAudioPatches()) {
sp<DeviceHalInterface> hwDevice = mOutput->audioHwDev->hwDevice();
@@ -4068,8 +4104,6 @@
*handle = AUDIO_PATCH_HANDLE_NONE;
}
if (configChanged) {
- mPrevOutDevice = type;
- mDeviceId = sinkPortId;
sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED);
}
return status;
@@ -4093,7 +4127,8 @@
{
status_t status = NO_ERROR;
- mOutDevice = AUDIO_DEVICE_NONE;
+ mPatch = audio_patch{};
+ mOutDeviceTypeAddrs.clear();
if (mOutput->audioHwDev->supportsAudioPatches()) {
sp<DeviceHalInterface> hwDevice = mOutput->audioHwDev->hwDevice();
@@ -4133,8 +4168,8 @@
// ----------------------------------------------------------------------------
AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
- audio_io_handle_t id, audio_devices_t device, bool systemReady, type_t type)
- : PlaybackThread(audioFlinger, output, id, device, type, systemReady),
+ audio_io_handle_t id, bool systemReady, type_t type)
+ : PlaybackThread(audioFlinger, output, id, type, systemReady),
// mAudioMixer below
// mFastMixer below
mFastMixerFutex(0),
@@ -4144,7 +4179,7 @@
// mNormalSink below
{
setMasterBalance(audioFlinger->getMasterBalance_l());
- ALOGV("MixerThread() id=%d device=%#x type=%d", id, device, type);
+ ALOGV("MixerThread() id=%d type=%d", id, type);
ALOGV("mSampleRate=%u, mChannelMask=%#x, mChannelCount=%u, mFormat=%#x, mFrameSize=%zu, "
"mFrameCount=%zu, mNormalFrameCount=%zu",
mSampleRate, mChannelMask, mChannelCount, mFormat, mFrameSize, mFrameCount,
@@ -4186,7 +4221,7 @@
// scheduled reliably with CFS. However, the BT A2DP HAL is
// bursty (does not pull at a regular rate) and so cannot operate with FastMixer.
initFastMixer = mFrameCount < mNormalFrameCount
- && (mOutDevice & AUDIO_DEVICE_OUT_ALL_A2DP) == 0;
+ && Intersection(outDeviceTypes(), getAudioDeviceOutAllA2dpSet()).empty();
break;
}
ALOGW_IF(initFastMixer == false && mFrameCount < mNormalFrameCount,
@@ -5357,39 +5392,7 @@
}
}
if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
-#ifdef ADD_BATTERY_DATA
- // when changing the audio output device, call addBatteryData to notify
- // the change
- if (mOutDevice != value) {
- uint32_t params = 0;
- // check whether speaker is on
- if (value & AUDIO_DEVICE_OUT_SPEAKER) {
- params |= IMediaPlayerService::kBatteryDataSpeakerOn;
- }
-
- audio_devices_t deviceWithoutSpeaker
- = AUDIO_DEVICE_OUT_ALL & ~AUDIO_DEVICE_OUT_SPEAKER;
- // check if any other device (except speaker) is on
- if (value & deviceWithoutSpeaker) {
- params |= IMediaPlayerService::kBatteryDataOtherAudioDeviceOn;
- }
-
- if (params != 0) {
- addBatteryData(params);
- }
- }
-#endif
-
- // forward device change to effects that have requested to be
- // aware of attached audio device.
- if (value != AUDIO_DEVICE_NONE) {
- a2dpDeviceChanged =
- (mOutDevice & AUDIO_DEVICE_OUT_ALL_A2DP) != (value & AUDIO_DEVICE_OUT_ALL_A2DP);
- mOutDevice = value;
- for (size_t i = 0; i < mEffectChains.size(); i++) {
- mEffectChains[i]->setDevice_l(mOutDevice);
- }
- }
+ LOG_FATAL("Should not set routing device in MixerThread");
}
if (status == NO_ERROR) {
@@ -5490,9 +5493,8 @@
// ----------------------------------------------------------------------------
AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger,
- AudioStreamOut* output, audio_io_handle_t id, audio_devices_t device,
- ThreadBase::type_t type, bool systemReady)
- : PlaybackThread(audioFlinger, output, id, device, type, systemReady)
+ AudioStreamOut* output, audio_io_handle_t id, ThreadBase::type_t type, bool systemReady)
+ : PlaybackThread(audioFlinger, output, id, type, systemReady)
{
setMasterBalance(audioFlinger->getMasterBalance_l());
}
@@ -5894,16 +5896,7 @@
AudioParameter param = AudioParameter(keyValuePair);
int value;
if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
- // forward device change to effects that have requested to be
- // aware of attached audio device.
- if (value != AUDIO_DEVICE_NONE) {
- a2dpDeviceChanged =
- (mOutDevice & AUDIO_DEVICE_OUT_ALL_A2DP) != (value & AUDIO_DEVICE_OUT_ALL_A2DP);
- mOutDevice = value;
- for (size_t i = 0; i < mEffectChains.size(); i++) {
- mEffectChains[i]->setDevice_l(mOutDevice);
- }
- }
+ LOG_FATAL("Should not set routing device in DirectOutputThread");
}
if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
// do not accept frame count changes if tracks are open as the track buffer
@@ -6115,8 +6108,8 @@
// ----------------------------------------------------------------------------
AudioFlinger::OffloadThread::OffloadThread(const sp<AudioFlinger>& audioFlinger,
- AudioStreamOut* output, audio_io_handle_t id, uint32_t device, bool systemReady)
- : DirectOutputThread(audioFlinger, output, id, device, OFFLOAD, systemReady),
+ AudioStreamOut* output, audio_io_handle_t id, bool systemReady)
+ : DirectOutputThread(audioFlinger, output, id, OFFLOAD, systemReady),
mPausedWriteLength(0), mPausedBytesRemaining(0), mKeepWakeLock(true),
mOffloadUnderrunPosition(~0LL)
{
@@ -6441,7 +6434,7 @@
AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger,
AudioFlinger::MixerThread* mainThread, audio_io_handle_t id, bool systemReady)
- : MixerThread(audioFlinger, mainThread->getOutput(), id, mainThread->outDevice(),
+ : MixerThread(audioFlinger, mainThread->getOutput(), id,
systemReady, DUPLICATING),
mWaitTimeMs(UINT_MAX)
{
@@ -6673,11 +6666,9 @@
AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger,
AudioStreamIn *input,
audio_io_handle_t id,
- audio_devices_t outDevice,
- audio_devices_t inDevice,
bool systemReady
) :
- ThreadBase(audioFlinger, id, outDevice, inDevice, RECORD, systemReady),
+ ThreadBase(audioFlinger, id, RECORD, systemReady),
mInput(input),
mSource(mInput),
mActiveTracks(&this->mLocalLog),
@@ -6709,8 +6700,9 @@
// TODO: We may also match on address as well as device type for
// AUDIO_DEVICE_IN_BUS, AUDIO_DEVICE_IN_BLUETOOTH_A2DP, AUDIO_DEVICE_IN_REMOTE_SUBMIX
- mTimestampCorrectedDevices = (audio_devices_t)property_get_int64(
- "audio.timestamp.corrected_input_devices",
+ // TODO: This property should be ensure that only contains one single device type.
+ mTimestampCorrectedDevice = (audio_devices_t)property_get_int64(
+ "audio.timestamp.corrected_input_device",
(int64_t)(mIsMsdDevice ? AUDIO_DEVICE_IN_BUS // turn on by default for MSD
: AUDIO_DEVICE_NONE));
@@ -8054,7 +8046,7 @@
{
// disable AEC and NS if the device is a BT SCO headset supporting those
// pre processings
- bool suspend = audio_is_bluetooth_sco_device(mInDevice) &&
+ bool suspend = audio_is_bluetooth_sco_device(inDeviceType()) &&
mAudioFlinger->btNrecIsOff();
if (mBtNrecSuspended.exchange(suspend) != suspend) {
for (size_t i = 0; i < mEffectChains.size(); i++) {
@@ -8119,34 +8111,11 @@
}
}
if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
- // forward device change to effects that have requested to be
- // aware of attached audio device.
- for (size_t i = 0; i < mEffectChains.size(); i++) {
- mEffectChains[i]->setDevice_l(value);
- }
-
- // store input device and output device but do not forward output device to audio HAL.
- // Note that status is ignored by the caller for output device
- // (see AudioFlinger::setParameters()
- if (audio_is_output_devices(value)) {
- mOutDevice = value;
- status = BAD_VALUE;
- } else {
- mInDevice = value;
- if (value != AUDIO_DEVICE_NONE) {
- mPrevInDevice = value;
- }
- checkBtNrec_l();
- }
+ LOG_FATAL("Should not set routing device in RecordThread");
}
if (param.getInt(String8(AudioParameter::keyInputSource), value) == NO_ERROR &&
mAudioSource != (audio_source_t)value) {
- // forward device change to effects that have requested to be
- // aware of attached audio device.
- for (size_t i = 0; i < mEffectChains.size(); i++) {
- mEffectChains[i]->setAudioSource_l((audio_source_t)value);
- }
- mAudioSource = (audio_source_t)value;
+ LOG_FATAL("Should not set audio source in RecordThread");
}
if (status == NO_ERROR) {
@@ -8348,11 +8317,11 @@
status_t status = NO_ERROR;
// store new device and send to effects
- mInDevice = patch->sources[0].ext.device.type;
+ mInDeviceTypeAddr.mType = patch->sources[0].ext.device.type;
+ mInDeviceTypeAddr.mAddress = patch->sources[0].ext.device.address;
audio_port_handle_t deviceId = patch->sources[0].id;
- mPatch = *patch;
for (size_t i = 0; i < mEffectChains.size(); i++) {
- mEffectChains[i]->setDevice_l(mInDevice);
+ mEffectChains[i]->setDevice_l(mInDeviceTypeAddr.mType);
}
checkBtNrec_l();
@@ -8391,10 +8360,9 @@
*handle = AUDIO_PATCH_HANDLE_NONE;
}
- if ((mInDevice != mPrevInDevice) || (mDeviceId != deviceId)) {
+ if ((mPatch.num_sources == 0) || (mPatch.sources[0].id != deviceId)) {
sendIoConfigEvent_l(AUDIO_INPUT_CONFIG_CHANGED);
- mPrevInDevice = mInDevice;
- mDeviceId = deviceId;
+ mPatch = *patch;
}
return status;
@@ -8404,7 +8372,8 @@
{
status_t status = NO_ERROR;
- mInDevice = AUDIO_DEVICE_NONE;
+ mPatch = audio_patch{};
+ mInDeviceTypeAddr.reset();
if (mInput->audioHwDev->supportsAudioPatches()) {
sp<DeviceHalInterface> hwDevice = mInput->audioHwDev->hwDevice();
@@ -8417,6 +8386,15 @@
return status;
}
+void AudioFlinger::RecordThread::updateOutDevices(const DeviceDescriptorBaseVector& outDevices)
+{
+ mOutDevices = outDevices;
+ mOutDeviceTypeAddrs = deviceTypeAddrsFromDescriptors(mOutDevices);
+ for (size_t i = 0; i < mEffectChains.size(); i++) {
+ mEffectChains[i]->setDevice_l(deviceTypesToBitMask(outDeviceTypes()));
+ }
+}
+
void AudioFlinger::RecordThread::addPatchTrack(const sp<PatchRecord>& record)
{
Mutex::Autolock _l(mLock);
@@ -8493,9 +8471,8 @@
AudioFlinger::MmapThread::MmapThread(
const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
- AudioHwDevice *hwDev, sp<StreamHalInterface> stream,
- audio_devices_t outDevice, audio_devices_t inDevice, bool systemReady)
- : ThreadBase(audioFlinger, id, outDevice, inDevice, MMAP, systemReady),
+ AudioHwDevice *hwDev, sp<StreamHalInterface> stream, bool systemReady)
+ : ThreadBase(audioFlinger, id, MMAP, systemReady),
mSessionId(AUDIO_SESSION_NONE),
mPortId(AUDIO_PORT_HANDLE_NONE),
mHalStream(stream), mHalDevice(hwDev->hwDevice()), mAudioHwDev(hwDev),
@@ -8861,26 +8838,7 @@
int value;
bool sendToHal = true;
if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
- audio_devices_t device = (audio_devices_t)value;
- // forward device change to effects that have requested to be
- // aware of attached audio device.
- if (device != AUDIO_DEVICE_NONE) {
- for (size_t i = 0; i < mEffectChains.size(); i++) {
- mEffectChains[i]->setDevice_l(device);
- }
- }
- if (audio_is_output_devices(device)) {
- mOutDevice = device;
- if (!isOutput()) {
- sendToHal = false;
- }
- } else {
- mInDevice = device;
- if (device != AUDIO_DEVICE_NONE) {
- mPrevInDevice = value;
- }
- // TODO: implement and call checkBtNrec_l();
- }
+ LOG_FATAL("Should not happen set routing device in MmapThread");
}
if (sendToHal) {
status = mHalStream->setParameters(keyValuePair);
@@ -8939,24 +8897,35 @@
// store new device and send to effects
audio_devices_t type = AUDIO_DEVICE_NONE;
audio_port_handle_t deviceId;
+ AudioDeviceTypeAddrVector sinkDeviceTypeAddrs;
+ AudioDeviceTypeAddr sourceDeviceTypeAddr;
+ uint32_t numDevices = 0;
if (isOutput()) {
for (unsigned int i = 0; i < patch->num_sinks; i++) {
+ LOG_ALWAYS_FATAL_IF(popcount(patch->sinks[i].ext.device.type) > 1
+ && !mAudioHwDev->supportsAudioPatches(),
+ "Enumerated device type(%#x) must not be used "
+ "as it does not support audio patches",
+ patch->sinks[i].ext.device.type);
type |= patch->sinks[i].ext.device.type;
+ sinkDeviceTypeAddrs.push_back(AudioDeviceTypeAddr(patch->sinks[i].ext.device.type,
+ patch->sinks[i].ext.device.address));
}
deviceId = patch->sinks[0].id;
+ numDevices = mPatch.num_sinks;
} else {
type = patch->sources[0].ext.device.type;
deviceId = patch->sources[0].id;
+ numDevices = mPatch.num_sources;
+ sourceDeviceTypeAddr.mType = patch->sources[0].ext.device.type;
+ sourceDeviceTypeAddr.mAddress = patch->sources[0].ext.device.address;
}
for (size_t i = 0; i < mEffectChains.size(); i++) {
mEffectChains[i]->setDevice_l(type);
}
- if (isOutput()) {
- mOutDevice = type;
- } else {
- mInDevice = type;
+ if (!isOutput()) {
// store new source and send to effects
if (mAudioSource != patch->sinks[0].ext.mix.usecase.source) {
mAudioSource = patch->sinks[0].ext.mix.usecase.source;
@@ -8993,26 +8962,21 @@
*handle = AUDIO_PATCH_HANDLE_NONE;
}
- if (isOutput() && (mPrevOutDevice != mOutDevice || mDeviceId != deviceId)) {
- mPrevOutDevice = type;
- sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED);
+ if (numDevices == 0 || mDeviceId != deviceId) {
+ if (isOutput()) {
+ sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED);
+ mOutDeviceTypeAddrs = sinkDeviceTypeAddrs;
+ } else {
+ sendIoConfigEvent_l(AUDIO_INPUT_CONFIG_CHANGED);
+ mInDeviceTypeAddr = sourceDeviceTypeAddr;
+ }
sp<MmapStreamCallback> callback = mCallback.promote();
if (mDeviceId != deviceId && callback != 0) {
mLock.unlock();
callback->onRoutingChanged(deviceId);
mLock.lock();
}
- mDeviceId = deviceId;
- }
- if (!isOutput() && (mPrevInDevice != mInDevice || mDeviceId != deviceId)) {
- mPrevInDevice = type;
- sendIoConfigEvent_l(AUDIO_INPUT_CONFIG_CHANGED);
- sp<MmapStreamCallback> callback = mCallback.promote();
- if (mDeviceId != deviceId && callback != 0) {
- mLock.unlock();
- callback->onRoutingChanged(deviceId);
- mLock.lock();
- }
+ mPatch = *patch;
mDeviceId = deviceId;
}
return status;
@@ -9022,7 +8986,9 @@
{
status_t status = NO_ERROR;
- mInDevice = AUDIO_DEVICE_NONE;
+ mPatch = audio_patch{};
+ mOutDeviceTypeAddrs.clear();
+ mInDeviceTypeAddr.reset();
bool supportsAudioPatches = mHalDevice->supportsAudioPatches(&supportsAudioPatches) == OK ?
supportsAudioPatches : false;
@@ -9198,9 +9164,8 @@
AudioFlinger::MmapPlaybackThread::MmapPlaybackThread(
const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
- AudioHwDevice *hwDev, AudioStreamOut *output,
- audio_devices_t outDevice, audio_devices_t inDevice, bool systemReady)
- : MmapThread(audioFlinger, id, hwDev, output->stream, outDevice, inDevice, systemReady),
+ AudioHwDevice *hwDev, AudioStreamOut *output, bool systemReady)
+ : MmapThread(audioFlinger, id, hwDev, output->stream, systemReady),
mStreamType(AUDIO_STREAM_MUSIC),
mStreamVolume(1.0),
mStreamMute(false),
@@ -9410,9 +9375,8 @@
AudioFlinger::MmapCaptureThread::MmapCaptureThread(
const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
- AudioHwDevice *hwDev, AudioStreamIn *input,
- audio_devices_t outDevice, audio_devices_t inDevice, bool systemReady)
- : MmapThread(audioFlinger, id, hwDev, input->stream, outDevice, inDevice, systemReady),
+ AudioHwDevice *hwDev, AudioStreamIn *input, bool systemReady)
+ : MmapThread(audioFlinger, id, hwDev, input->stream, systemReady),
mInput(input)
{
snprintf(mThreadName, kThreadNameLength, "AudioMmapIn_%X", id);
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 34a3f34..a70b7ae 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -37,8 +37,7 @@
static const char *threadTypeToString(type_t type);
ThreadBase(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
- audio_devices_t outDevice, audio_devices_t inDevice, type_t type,
- bool systemReady);
+ type_t type, bool systemReady);
virtual ~ThreadBase();
virtual status_t readyToRun();
@@ -52,6 +51,7 @@
CFG_EVENT_SET_PARAMETER,
CFG_EVENT_CREATE_AUDIO_PATCH,
CFG_EVENT_RELEASE_AUDIO_PATCH,
+ CFG_EVENT_UPDATE_OUT_DEVICE,
};
class ConfigEventData: public RefBase {
@@ -219,6 +219,28 @@
virtual ~ReleaseAudioPatchConfigEvent() {}
};
+ class UpdateOutDevicesConfigEventData : public ConfigEventData {
+ public:
+ explicit UpdateOutDevicesConfigEventData(const DeviceDescriptorBaseVector& outDevices) :
+ mOutDevices(outDevices) {}
+
+ virtual void dump(char *buffer, size_t size) {
+ snprintf(buffer, size, "Devices: %s", android::toString(mOutDevices).c_str());
+ }
+
+ DeviceDescriptorBaseVector mOutDevices;
+ };
+
+ class UpdateOutDevicesConfigEvent : public ConfigEvent {
+ public:
+ explicit UpdateOutDevicesConfigEvent(const DeviceDescriptorBaseVector& outDevices) :
+ ConfigEvent(CFG_EVENT_UPDATE_OUT_DEVICE) {
+ mData = new UpdateOutDevicesConfigEventData(outDevices);
+ }
+
+ virtual ~UpdateOutDevicesConfigEvent();
+ };
+
class PMDeathRecipient : public IBinder::DeathRecipient {
public:
explicit PMDeathRecipient(const wp<ThreadBase>& thread) : mThread(thread) {}
@@ -278,19 +300,26 @@
status_t sendCreateAudioPatchConfigEvent(const struct audio_patch *patch,
audio_patch_handle_t *handle);
status_t sendReleaseAudioPatchConfigEvent(audio_patch_handle_t handle);
+ status_t sendUpdateOutDeviceConfigEvent(
+ const DeviceDescriptorBaseVector& outDevices);
void processConfigEvents_l();
virtual void cacheParameters_l() = 0;
virtual status_t createAudioPatch_l(const struct audio_patch *patch,
audio_patch_handle_t *handle) = 0;
virtual status_t releaseAudioPatch_l(const audio_patch_handle_t handle) = 0;
+ virtual void updateOutDevices(const DeviceDescriptorBaseVector& outDevices);
virtual void toAudioPortConfig(struct audio_port_config *config) = 0;
// see note at declaration of mStandby, mOutDevice and mInDevice
bool standby() const { return mStandby; }
- audio_devices_t outDevice() const { return mOutDevice; }
- audio_devices_t inDevice() const { return mInDevice; }
- audio_devices_t getDevice() const { return isOutput() ? mOutDevice : mInDevice; }
+ const DeviceTypeSet outDeviceTypes() const {
+ return getAudioDeviceTypes(mOutDeviceTypeAddrs);
+ }
+ audio_devices_t inDeviceType() const { return mInDeviceTypeAddr.mType; }
+ DeviceTypeSet getDeviceTypes() const {
+ return isOutput() ? outDeviceTypes() : DeviceTypeSet({inDeviceType()});
+ }
virtual bool isOutput() const = 0;
@@ -502,26 +531,21 @@
// HAL format if Fastmixer is used.
audio_format_t mHALFormat;
size_t mBufferSize; // HAL buffer size for read() or write()
-
+ AudioDeviceTypeAddrVector mOutDeviceTypeAddrs; // output device types and addresses
+ AudioDeviceTypeAddr mInDeviceTypeAddr; // input device type and address
Vector< sp<ConfigEvent> > mConfigEvents;
Vector< sp<ConfigEvent> > mPendingConfigEvents; // events awaiting system ready
// These fields are written and read by thread itself without lock or barrier,
- // and read by other threads without lock or barrier via standby(), outDevice()
- // and inDevice().
+ // and read by other threads without lock or barrier via standby(), outDeviceTypes()
+ // and inDeviceType().
// Because of the absence of a lock or barrier, any other thread that reads
// these fields must use the information in isolation, or be prepared to deal
// with possibility that it might be inconsistent with other information.
bool mStandby; // Whether thread is currently in standby.
- audio_devices_t mOutDevice; // output device
- audio_devices_t mInDevice; // input device
- audio_devices_t mPrevOutDevice; // previous output device
- audio_devices_t mPrevInDevice; // previous input device
+
struct audio_patch mPatch;
- /**
- * @brief mDeviceId current device port unique identifier
- */
- audio_port_handle_t mDeviceId = AUDIO_PORT_HANDLE_NONE;
+
audio_source_t mAudioSource;
const audio_io_handle_t mId;
@@ -544,7 +568,8 @@
ExtendedTimestamp mTimestamp;
TimestampVerifier< // For timestamp statistics.
int64_t /* frame count */, int64_t /* time ns */> mTimestampVerifier;
- audio_devices_t mTimestampCorrectedDevices = AUDIO_DEVICE_NONE;
+ // Timestamp corrected device should be a single device.
+ audio_devices_t mTimestampCorrectedDevice = AUDIO_DEVICE_NONE;
// ThreadLoop statistics per iteration.
int64_t mLastIoBeginNs = -1;
@@ -719,7 +744,7 @@
static const nsecs_t kMaxNextBufferDelayNs = 100000000;
PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
- audio_io_handle_t id, audio_devices_t device, type_t type, bool systemReady);
+ audio_io_handle_t id, type_t type, bool systemReady);
virtual ~PlaybackThread();
// Thread virtuals
@@ -886,10 +911,10 @@
}
bool isTimestampCorrectionEnabled() const override {
- const audio_devices_t device =
- mOutDevice & mTimestampCorrectedDevices;
- return audio_is_output_devices(device) && popcount(device) > 0;
+ return audio_is_output_devices(mTimestampCorrectedDevice)
+ && outDeviceTypes().count(mTimestampCorrectedDevice) != 0;
}
+
protected:
// updated by readOutputParameters_l()
size_t mNormalFrameCount; // normal mixer and effects
@@ -1171,7 +1196,6 @@
MixerThread(const sp<AudioFlinger>& audioFlinger,
AudioStreamOut* output,
audio_io_handle_t id,
- audio_devices_t device,
bool systemReady,
type_t type = MIXER);
virtual ~MixerThread();
@@ -1269,8 +1293,8 @@
public:
DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
- audio_io_handle_t id, audio_devices_t device, bool systemReady)
- : DirectOutputThread(audioFlinger, output, id, device, DIRECT, systemReady) { }
+ audio_io_handle_t id, bool systemReady)
+ : DirectOutputThread(audioFlinger, output, id, DIRECT, systemReady) { }
virtual ~DirectOutputThread();
@@ -1305,8 +1329,7 @@
bool mVolumeShaperActive = false;
DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
- audio_io_handle_t id, audio_devices_t device, ThreadBase::type_t type,
- bool systemReady);
+ audio_io_handle_t id, ThreadBase::type_t type, bool systemReady);
void processVolume_l(Track *track, bool lastTrack);
// prepareTracks_l() tells threadLoop_mix() the name of the single active track
@@ -1345,7 +1368,7 @@
public:
OffloadThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
- audio_io_handle_t id, uint32_t device, bool systemReady);
+ audio_io_handle_t id, bool systemReady);
virtual ~OffloadThread() {};
virtual void flushHw_l();
@@ -1516,8 +1539,6 @@
RecordThread(const sp<AudioFlinger>& audioFlinger,
AudioStreamIn *input,
audio_io_handle_t id,
- audio_devices_t outDevice,
- audio_devices_t inDevice,
bool systemReady
);
virtual ~RecordThread();
@@ -1577,6 +1598,7 @@
virtual status_t createAudioPatch_l(const struct audio_patch *patch,
audio_patch_handle_t *handle);
virtual status_t releaseAudioPatch_l(const audio_patch_handle_t handle);
+ void updateOutDevices(const DeviceDescriptorBaseVector& outDevices) override;
void addPatchTrack(const sp<PatchRecord>& record);
void deletePatchTrack(const sp<PatchRecord>& record);
@@ -1629,8 +1651,8 @@
bool isTimestampCorrectionEnabled() const override {
// checks popcount for exactly one device.
- return audio_is_input_device(
- mInDevice & mTimestampCorrectedDevices);
+ return audio_is_input_device(mTimestampCorrectedDevice)
+ && inDeviceType() == mTimestampCorrectedDevice;
}
protected:
@@ -1709,6 +1731,8 @@
std::atomic_bool mBtNrecSuspended;
int64_t mFramesRead = 0; // continuous running counter.
+
+ DeviceDescriptorBaseVector mOutDevices;
};
class MmapThread : public ThreadBase
@@ -1718,8 +1742,7 @@
#include "MmapTracks.h"
MmapThread(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
- AudioHwDevice *hwDev, sp<StreamHalInterface> stream,
- audio_devices_t outDevice, audio_devices_t inDevice, bool systemReady);
+ AudioHwDevice *hwDev, sp<StreamHalInterface> stream, bool systemReady);
virtual ~MmapThread();
virtual void configure(const audio_attributes_t *attr,
@@ -1793,6 +1816,11 @@
void dumpInternals_l(int fd, const Vector<String16>& args) override;
void dumpTracks_l(int fd, const Vector<String16>& args) override;
+ /**
+ * @brief mDeviceId current device port unique identifier
+ */
+ audio_port_handle_t mDeviceId = AUDIO_PORT_HANDLE_NONE;
+
audio_attributes_t mAttr;
audio_session_t mSessionId;
audio_port_handle_t mPortId;
@@ -1813,8 +1841,7 @@
public:
MmapPlaybackThread(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
- AudioHwDevice *hwDev, AudioStreamOut *output,
- audio_devices_t outDevice, audio_devices_t inDevice, bool systemReady);
+ AudioHwDevice *hwDev, AudioStreamOut *output, bool systemReady);
virtual ~MmapPlaybackThread() {}
virtual void configure(const audio_attributes_t *attr,
@@ -1863,8 +1890,7 @@
public:
MmapCaptureThread(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
- AudioHwDevice *hwDev, AudioStreamIn *input,
- audio_devices_t outDevice, audio_devices_t inDevice, bool systemReady);
+ AudioHwDevice *hwDev, AudioStreamIn *input, bool systemReady);
virtual ~MmapCaptureThread() {}
AudioStreamIn* clearInput();