Refactor audio device type in audio flinger.

As audio device type must not be used as a bit mask, there is a
requirement to refactor the code in audio flinger. This CL includes:
1. Use DeviceTypeSet for recording output devices in Threads. The input
and output device types in Threads will only be updated when creating
an audio patch.
2. Use helper functions in audio flinger for checking whether an audio
device type is a certain category.
3. Use DeviceDescriptorBaseVector as vector of DeviceDescriptorBase.
DeviceDescriptorBaseVector will be used in RecordThread to record output
devices, which will be used in audio effect.
4. Do not use set parameters when communicating output devices to
RecordThread. Instead, adding a new event in Thread to update output
devices directly.

Bug: 135621476
Test: atest AudioTrackTest AudioRecordTest AudioPlaybackCaptureTest
Test: atest AudioHostTest AudioServiceHostTest RoutingTest
Test: atest AudioEffectTest BassBoostTest DynamicsProcessingTest
Test: atest AAudioTests
Test: audio smoke test, run OboeTester
Change-Id: I87f3e59fd01b0b100232d61a9abbc471c61110c4
gugelfrei
jiabin 5 years ago
parent c76250c827
commit c52b1ffec2

@ -50,6 +50,10 @@ const DeviceTypeSet& getAudioDeviceInAllSet() {
}
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 @@ std::string dumpDeviceTypes(const DeviceTypeSet &deviceTypes) {
return ret;
}
std::string toString(const DeviceTypeSet& deviceTypes) {
std::string ret;
deviceTypesToString(deviceTypes, ret);
return ret;
}
} // namespace android

@ -26,6 +26,11 @@ bool AudioDeviceTypeAddr::equals(const AudioDeviceTypeAddr& other) const {
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 @@ status_t AudioDeviceTypeAddr::writeToParcel(Parcel *parcel) const {
return status;
}
DeviceTypeSet getAudioDeviceTypes(const AudioDeviceTypeAddrVector& deviceTypeAddrs) {
DeviceTypeSet deviceTypes;
for (const auto& deviceTypeAddr : deviceTypeAddrs) {
deviceTypes.insert(deviceTypeAddr.mType);
}
return deviceTypes;
}
}

@ -137,4 +137,25 @@ status_t DeviceDescriptorBase::readFromParcel(const Parcel *parcel)
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

@ -123,5 +123,10 @@ bool deviceTypesToString(const DeviceTypeSet& deviceTypes, std::string &str);
std::string dumpDeviceTypes(const DeviceTypeSet& deviceTypes);
/**
* Return human readable string for device types.
*/
std::string toString(const DeviceTypeSet& deviceTypes);
} // namespace android

@ -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 @@ struct AudioDeviceTypeAddr : public Parcelable {
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 @@ struct AudioDeviceTypeAddr : public Parcelable {
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);
}

@ -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>
@ -64,4 +67,17 @@ protected:
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

@ -1357,6 +1357,13 @@ void AudioFlinger::broacastParametersToRecordThreads_l(const String8& keyValuePa
}
}
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 @@ sp<AudioFlinger::ThreadBase> AudioFlinger::openOutput_l(audio_module_handle_t mo
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 @@ sp<AudioFlinger::ThreadBase> AudioFlinger::openOutput_l(audio_module_handle_t mo
} 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 @@ sp<AudioFlinger::ThreadBase> AudioFlinger::openInput_l(audio_module_handle_t mod
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 @@ sp<AudioFlinger::ThreadBase> AudioFlinger::openInput_l(audio_module_handle_t mod
// 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 @@ AudioFlinger::PlaybackThread *AudioFlinger::primaryPlaybackThread_l() const
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

@ -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 @@ using effect_buffer_t = int16_t;
// 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 @@ using effect_buffer_t = int16_t;
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);

@ -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 @@ status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa
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_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa
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 @@ status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa
}
}
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);

@ -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 @@ const char *AudioFlinger::ThreadBase::threadTypeToString(AudioFlinger::ThreadBas
}
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 @@ AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, audio
// 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 @@ status_t AudioFlinger::ThreadBase::sendReleaseAudioPatchConfigEvent(
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 @@ void AudioFlinger::ThreadBase::processConfigEvents_l()
}
} 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 @@ void AudioFlinger::ThreadBase::dumpBase_l(int fd, const Vector<String16>& args _
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 @@ void AudioFlinger::ThreadBase::clearPowerManager()
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 @@ sp<AudioFlinger::EffectHandle> AudioFlinger::ThreadBase::createEffect_l(
}
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 @@ status_t AudioFlinger::ThreadBase::addEffect_l(const sp<EffectModule>& effect)
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 @@ void AudioFlinger::ThreadBase::sendStatistics(bool force)
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 @@ void AudioFlinger::ThreadBase::sendStatistics(bool force)
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 @@ AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinge
// 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 @@ void AudioFlinger::PlaybackThread::checkSilentMode_l()
{
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 @@ void AudioFlinger::PlaybackThread::cacheParameters_l()
// 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 @@ bool AudioFlinger::PlaybackThread::threadLoop()
// 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 @@ bool AudioFlinger::PlaybackThread::threadLoop()
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 @@ status_t AudioFlinger::PlaybackThread::createAudioPatch_l(const struct audio_pat
// 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 @@ status_t AudioFlinger::PlaybackThread::createAudioPatch_l(const struct audio_pat
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 @@ status_t AudioFlinger::PlaybackThread::createAudioPatch_l(const struct audio_pat
*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 AudioFlinger::PlaybackThread::releaseAudioPatch_l(const audio_patch_han
{
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 @@ void AudioFlinger::PlaybackThread::toAudioPortConfig(struct audio_port_config *c
// ----------------------------------------------------------------------------
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 @@ AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, Aud
// 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 @@ AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, Aud
// 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 @@ bool AudioFlinger::MixerThread::checkForNewParameter_l(const String8& keyValuePa
}
}
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 @@ void AudioFlinger::MixerThread::cacheParameters_l()
// ----------------------------------------------------------------------------
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 @@ bool AudioFlinger::DirectOutputThread::checkForNewParameter_l(const String8& key
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 @@ void AudioFlinger::AsyncCallbackThread::setAsyncError()
// ----------------------------------------------------------------------------
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 @@ void AudioFlinger::OffloadThread::invalidateTracks(audio_stream_type_t streamTyp
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 @@ void AudioFlinger::DuplicatingThread::cacheParameters_l()
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 @@ AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger,
// 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 @@ void AudioFlinger::RecordThread::checkBtNrec_l()
{
// 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 @@ bool AudioFlinger::RecordThread::checkForNewParameter_l(const String8& keyValueP
}
}
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 AudioFlinger::RecordThread::createAudioPatch_l(const struct audio_patch
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 @@ status_t AudioFlinger::RecordThread::createAudioPatch_l(const struct audio_patch
*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 AudioFlinger::RecordThread::releaseAudioPatch_l(const audio_patch_handl
{
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 @@ status_t AudioFlinger::RecordThread::releaseAudioPatch_l(const audio_patch_handl
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 @@ status_t AudioFlinger::MmapThreadHandle::standby()
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 @@ bool AudioFlinger::MmapThread::checkForNewParameter_l(const String8& keyValuePai
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 @@ status_t AudioFlinger::MmapThread::createAudioPatch_l(const struct audio_patch *
// 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 @@ status_t AudioFlinger::MmapThread::createAudioPatch_l(const struct audio_patch *
*handle = AUDIO_PATCH_HANDLE_NONE;
}
if (isOutput() && (mPrevOutDevice != mOutDevice || mDeviceId != deviceId)) {
mPrevOutDevice = type;
sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED);
sp<MmapStreamCallback> callback = mCallback.promote();
if (mDeviceId != deviceId && callback != 0) {
mLock.unlock();
callback->onRoutingChanged(deviceId);
mLock.lock();
if (numDevices == 0 || mDeviceId != deviceId) {
if (isOutput()) {
sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED);
mOutDeviceTypeAddrs = sinkDeviceTypeAddrs;
} else {
sendIoConfigEvent_l(AUDIO_INPUT_CONFIG_CHANGED);
mInDeviceTypeAddr = sourceDeviceTypeAddr;
}
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 AudioFlinger::MmapThread::releaseAudioPatch_l(const audio_patch_handle_
{
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 @@ void AudioFlinger::MmapThread::dumpTracks_l(int fd, const Vector<String16>& args
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 @@ void AudioFlinger::MmapPlaybackThread::dumpInternals_l(int fd, const Vector<Stri
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);

@ -37,8 +37,7 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ protected:
// 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 @@ protected:
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 @@ public:
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 @@ public:
}
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 @@ public:
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 @@ class DirectOutputThread : public PlaybackThread {
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 @@ protected:
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 @@ class OffloadThread : public DirectOutputThread {
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ private:
std::atomic_bool mBtNrecSuspended;
int64_t mFramesRead = 0; // continuous running counter.
DeviceDescriptorBaseVector mOutDevices;
};
class MmapThread : public ThreadBase
@ -1718,8 +1742,7 @@ class MmapThread : public ThreadBase
#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 @@ class MmapThread : public ThreadBase
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 @@ class MmapPlaybackThread : public MmapThread, public VolumeInterface
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 @@ class MmapCaptureThread : public MmapThread
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();

Loading…
Cancel
Save