Merge changes from topic "mvAudioDeviceTypeAddr"

am: 0287266a3e

Change-Id: Ib4100bbd5df7ea6f99a7e9760dded5055254c7ec
gugelfrei
jiabin 5 years ago committed by android-build-merger
commit 4f4f865905

@ -1,7 +1,15 @@
cc_library_headers {
name: "libaudioclient_headers",
vendor_available: true,
export_include_dirs: ["include"],
header_libs: [
"libaudiofoundation_headers",
],
export_include_dirs: [
"include",
],
export_header_lib_headers: [
"libaudiofoundation_headers",
],
}
cc_library_shared {
@ -13,6 +21,7 @@ cc_library_shared {
"AudioVolumeGroup.cpp",
],
shared_libs: [
"libaudiofoundation",
"libaudioutils",
"libbinder",
"libcutils",
@ -63,6 +72,7 @@ cc_library_shared {
"TrackPlayerBase.cpp",
],
shared_libs: [
"libaudiofoundation",
"libaudioutils",
"libaudiopolicy",
"libaudiomanager",

@ -21,22 +21,6 @@
namespace android {
//
// AudioDeviceTypeAddr implementation
//
status_t AudioDeviceTypeAddr::readFromParcel(Parcel *parcel) {
mType = (audio_devices_t) parcel->readInt32();
mAddress = parcel->readString8();
return NO_ERROR;
}
status_t AudioDeviceTypeAddr::writeToParcel(Parcel *parcel) const {
parcel->writeInt32((int32_t) mType);
parcel->writeString8(mAddress);
return NO_ERROR;
}
//
// AudioMixMatchCriterion implementation
//

@ -392,20 +392,18 @@ public:
virtual status_t openOutput(audio_module_handle_t module,
audio_io_handle_t *output,
audio_config_t *config,
audio_devices_t *devices,
const String8& address,
const sp<DeviceDescriptorBase>& device,
uint32_t *latencyMs,
audio_output_flags_t flags)
{
if (output == NULL || config == NULL || devices == NULL || latencyMs == NULL) {
if (output == nullptr || config == nullptr || device == nullptr || latencyMs == nullptr) {
return BAD_VALUE;
}
Parcel data, reply;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
data.writeInt32(module);
data.write(config, sizeof(audio_config_t));
data.writeInt32(*devices);
data.writeString8(address);
data.writeParcelable(*device);
data.writeInt32((int32_t) flags);
status_t status = remote()->transact(OPEN_OUTPUT, data, &reply);
if (status != NO_ERROR) {
@ -420,7 +418,6 @@ public:
*output = (audio_io_handle_t)reply.readInt32();
ALOGV("openOutput() returned output, %d", *output);
reply.read(config, sizeof(audio_config_t));
*devices = (audio_devices_t)reply.readInt32();
*latencyMs = reply.readInt32();
return NO_ERROR;
}
@ -1200,19 +1197,21 @@ status_t BnAudioFlinger::onTransact(
if (data.read(&config, sizeof(audio_config_t)) != NO_ERROR) {
ALOGE("b/23905951");
}
audio_devices_t devices = (audio_devices_t)data.readInt32();
String8 address(data.readString8());
sp<DeviceDescriptorBase> device = new DeviceDescriptorBase(AUDIO_DEVICE_NONE);
status_t status = NO_ERROR;
if ((status = data.readParcelable(device.get())) != NO_ERROR) {
reply->writeInt32((int32_t)status);
return NO_ERROR;
}
audio_output_flags_t flags = (audio_output_flags_t) data.readInt32();
uint32_t latencyMs = 0;
audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
status_t status = openOutput(module, &output, &config,
&devices, address, &latencyMs, flags);
status = openOutput(module, &output, &config, device, &latencyMs, flags);
ALOGV("OPEN_OUTPUT output, %d", output);
reply->writeInt32((int32_t)status);
if (status == NO_ERROR) {
reply->writeInt32((int32_t)output);
reply->write(&config, sizeof(audio_config_t));
reply->writeInt32(devices);
reply->writeInt32(latencyMs);
}
return NO_ERROR;

@ -18,9 +18,10 @@
#ifndef ANDROID_AUDIO_POLICY_H
#define ANDROID_AUDIO_POLICY_H
#include <binder/Parcel.h>
#include <media/AudioDeviceTypeAddr.h>
#include <system/audio.h>
#include <system/audio_policy.h>
#include <binder/Parcel.h>
#include <utils/String8.h>
#include <utils/Vector.h>
@ -60,19 +61,6 @@ namespace android {
#define MAX_MIXES_PER_POLICY 10
#define MAX_CRITERIA_PER_MIX 20
class AudioDeviceTypeAddr {
public:
AudioDeviceTypeAddr() {}
AudioDeviceTypeAddr(audio_devices_t type, String8 address) :
mType(type), mAddress(address) {}
status_t readFromParcel(Parcel *parcel);
status_t writeToParcel(Parcel *parcel) const;
audio_devices_t mType;
String8 mAddress;
};
class AudioMixMatchCriterion {
public:
AudioMixMatchCriterion() {}

@ -19,6 +19,7 @@
#include <sys/types.h>
#include <media/AudioDeviceTypeAddr.h>
#include <media/AudioPolicy.h>
#include <media/AudioProductStrategy.h>
#include <media/AudioVolumeGroup.h>

@ -27,6 +27,7 @@
#include <binder/Parcel.h>
#include <binder/Parcelable.h>
#include <media/AudioClient.h>
#include <media/DeviceDescriptorBase.h>
#include <media/IAudioTrack.h>
#include <media/IAudioFlingerClient.h>
#include <system/audio.h>
@ -404,8 +405,7 @@ public:
virtual status_t openOutput(audio_module_handle_t module,
audio_io_handle_t *output,
audio_config_t *config,
audio_devices_t *devices,
const String8& address,
const sp<DeviceDescriptorBase>& device,
uint32_t *latencyMs,
audio_output_flags_t flags) = 0;
virtual audio_io_handle_t openDuplicateOutput(audio_io_handle_t output1,

@ -23,6 +23,7 @@
#include <utils/RefBase.h>
#include <utils/Errors.h>
#include <binder/IInterface.h>
#include <media/AudioDeviceTypeAddr.h>
#include <media/AudioSystem.h>
#include <media/AudioPolicy.h>
#include <media/IAudioPolicyServiceClient.h>

@ -4,22 +4,22 @@ cc_library_headers {
export_include_dirs: ["include"],
header_libs: [
"libaudio_system_headers",
"libaudioclient_headers",
"libmedia_headers",
"libmedia_helper_headers",
],
export_header_lib_headers: [
"libaudio_system_headers",
"libaudioclient_headers",
"libmedia_headers",
"libmedia_helper_headers",
],
}
cc_library_shared {
name: "libaudiofoundation",
vendor_available: true,
double_loadable: true,
srcs: [
"AudioContainers.cpp",
"AudioDeviceTypeAddr.cpp",
"AudioGain.cpp",
"AudioPort.cpp",
"AudioProfile.cpp",

@ -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

@ -0,0 +1,57 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <media/AudioDeviceTypeAddr.h>
namespace android {
const char* AudioDeviceTypeAddr::getAddress() const {
return mAddress.c_str();
}
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;
status = parcel->readUtf8FromUtf16(&mAddress);
return status;
}
status_t AudioDeviceTypeAddr::writeToParcel(Parcel *parcel) const {
status_t status;
if ((status = parcel->writeUint32(mType)) != NO_ERROR) return status;
status = parcel->writeUtf8AsUtf16(mAddress);
return status;
}
DeviceTypeSet getAudioDeviceTypes(const AudioDeviceTypeAddrVector& deviceTypeAddrs) {
DeviceTypeSet deviceTypes;
for (const auto& deviceTypeAddr : deviceTypeAddrs) {
deviceTypes.insert(deviceTypeAddr.mType);
}
return deviceTypes;
}
}

@ -27,11 +27,11 @@ namespace android {
DeviceDescriptorBase::DeviceDescriptorBase(audio_devices_t type) :
AudioPort("", AUDIO_PORT_TYPE_DEVICE,
audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK :
AUDIO_PORT_ROLE_SOURCE),
mDeviceType(type)
AUDIO_PORT_ROLE_SOURCE)
{
mDeviceTypeAddr.mType = type;
if (audio_is_remote_submix_device(type)) {
mAddress = "0";
mDeviceTypeAddr.mAddress = "0";
}
}
@ -55,22 +55,22 @@ void DeviceDescriptorBase::toAudioPortConfig(struct audio_port_config *dstConfig
AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig);
dstConfig->role = audio_is_output_device(mDeviceType) ?
dstConfig->role = audio_is_output_device(mDeviceTypeAddr.mType) ?
AUDIO_PORT_ROLE_SINK : AUDIO_PORT_ROLE_SOURCE;
dstConfig->type = AUDIO_PORT_TYPE_DEVICE;
dstConfig->ext.device.type = mDeviceType;
dstConfig->ext.device.type = mDeviceTypeAddr.mType;
(void)audio_utils_strlcpy_zerofill(dstConfig->ext.device.address, mAddress.c_str());
(void)audio_utils_strlcpy_zerofill(dstConfig->ext.device.address, mDeviceTypeAddr.getAddress());
}
void DeviceDescriptorBase::toAudioPort(struct audio_port *port) const
{
ALOGV("DeviceDescriptorBase::toAudioPort() handle %d type %08x", mId, mDeviceType);
ALOGV("DeviceDescriptorBase::toAudioPort() handle %d type %08x", mId, mDeviceTypeAddr.mType);
AudioPort::toAudioPort(port);
toAudioPortConfig(&port->active_config);
port->id = mId;
port->ext.device.type = mDeviceType;
(void)audio_utils_strlcpy_zerofill(port->ext.device.address, mAddress.c_str());
port->ext.device.type = mDeviceTypeAddr.mType;
(void)audio_utils_strlcpy_zerofill(port->ext.device.address, mDeviceTypeAddr.getAddress());
}
void DeviceDescriptorBase::dump(std::string *dst, int spaces, int index,
@ -86,10 +86,11 @@ void DeviceDescriptorBase::dump(std::string *dst, int spaces, int index,
}
dst->append(base::StringPrintf("%*s- type: %-48s\n",
spaces, "", ::android::toString(mDeviceType).c_str()));
spaces, "", ::android::toString(mDeviceTypeAddr.mType).c_str()));
if (mAddress.size() != 0) {
dst->append(base::StringPrintf("%*s- address: %-32s\n", spaces, "", mAddress.c_str()));
if (mDeviceTypeAddr.mAddress.size() != 0) {
dst->append(base::StringPrintf(
"%*s- address: %-32s\n", spaces, "", mDeviceTypeAddr.getAddress()));
}
AudioPort::dump(dst, spaces, verbose);
}
@ -97,15 +98,15 @@ void DeviceDescriptorBase::dump(std::string *dst, int spaces, int index,
std::string DeviceDescriptorBase::toString() const
{
std::stringstream sstream;
sstream << "type:0x" << std::hex << type() << ",@:" << mAddress;
sstream << "type:0x" << std::hex << type() << ",@:" << mDeviceTypeAddr.mAddress;
return sstream.str();
}
void DeviceDescriptorBase::log() const
{
ALOGI("Device id:%d type:0x%08X:%s, addr:%s", mId, mDeviceType,
::android::toString(mDeviceType).c_str(),
mAddress.c_str());
ALOGI("Device id:%d type:0x%08X:%s, addr:%s", mId, mDeviceTypeAddr.mType,
::android::toString(mDeviceTypeAddr.mType).c_str(),
mDeviceTypeAddr.getAddress());
AudioPort::log(" ");
}
@ -115,8 +116,7 @@ bool DeviceDescriptorBase::equals(const sp<DeviceDescriptorBase> &other) const
return other != nullptr &&
static_cast<const AudioPort*>(this)->equals(other) &&
static_cast<const AudioPortConfig*>(this)->equals(other) &&
mAddress.compare(other->address()) == 0 &&
mDeviceType == other->type();
mDeviceTypeAddr.equals(other->mDeviceTypeAddr);
}
status_t DeviceDescriptorBase::writeToParcel(Parcel *parcel) const
@ -124,8 +124,7 @@ status_t DeviceDescriptorBase::writeToParcel(Parcel *parcel) const
status_t status = NO_ERROR;
if ((status = AudioPort::writeToParcel(parcel)) != NO_ERROR) return status;
if ((status = AudioPortConfig::writeToParcel(parcel)) != NO_ERROR) return status;
if ((status = parcel->writeUtf8AsUtf16(mAddress)) != NO_ERROR) return status;
if ((status = parcel->writeUint32(mDeviceType)) != NO_ERROR) return status;
if ((status = parcel->writeParcelable(mDeviceTypeAddr)) != NO_ERROR) return status;
return status;
}
@ -134,9 +133,29 @@ status_t DeviceDescriptorBase::readFromParcel(const Parcel *parcel)
status_t status = NO_ERROR;
if ((status = AudioPort::readFromParcel(parcel)) != NO_ERROR) return status;
if ((status = AudioPortConfig::readFromParcel(parcel)) != NO_ERROR) return status;
if ((status = parcel->readUtf8FromUtf16(&mAddress)) != NO_ERROR) return status;
if ((status = parcel->readUint32(&mDeviceType)) != NO_ERROR) return status;
if ((status = parcel->readParcelable(&mDeviceTypeAddr)) != NO_ERROR) return status;
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

@ -17,6 +17,7 @@
#pragma once
#include <algorithm>
#include <functional>
#include <iterator>
#include <set>
#include <vector>
@ -78,6 +79,11 @@ static inline bool isSingleDeviceType(const DeviceTypeSet& deviceTypes,
return deviceTypes.size() == 1 && p(*(deviceTypes.begin()));
}
static inline bool areAllOfSameDeviceType(const DeviceTypeSet& deviceTypes,
std::function<bool(audio_devices_t)> p) {
return std::all_of(deviceTypes.begin(), deviceTypes.end(), p);
}
static inline void resetDeviceTypes(DeviceTypeSet& deviceTypes, audio_devices_t typeToAdd) {
deviceTypes.clear();
deviceTypes.insert(typeToAdd);
@ -117,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

@ -0,0 +1,57 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#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>
namespace android {
struct AudioDeviceTypeAddr : public Parcelable {
AudioDeviceTypeAddr() = default;
AudioDeviceTypeAddr(audio_devices_t type, const std::string& address) :
mType(type), mAddress(address) {}
const char* getAddress() const;
bool equals(const AudioDeviceTypeAddr& other) const;
void reset();
status_t readFromParcel(const Parcel *parcel) override;
status_t writeToParcel(Parcel *parcel) const override;
audio_devices_t mType = AUDIO_DEVICE_NONE;
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,9 +16,13 @@
#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>
#include <cutils/config_utils.h>
#include <system/audio.h>
@ -34,9 +38,10 @@ public:
virtual ~DeviceDescriptorBase() {}
audio_devices_t type() const { return mDeviceType; }
std::string address() const { return mAddress; }
void setAddress(const std::string &address) { mAddress = address; }
audio_devices_t type() const { return mDeviceTypeAddr.mType; }
std::string address() const { return mDeviceTypeAddr.mAddress; }
void setAddress(const std::string &address) { mDeviceTypeAddr.mAddress = address; }
const AudioDeviceTypeAddr& getDeviceTypeAddr() const { return mDeviceTypeAddr; }
// AudioPortConfig
virtual sp<AudioPort> getAudioPort() const {
@ -59,8 +64,20 @@ public:
status_t readFromParcel(const Parcel* parcel) override;
protected:
std::string mAddress{""};
audio_devices_t mDeviceType;
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

@ -233,14 +233,14 @@ status_t DeviceHalHidl::getInputBufferSize(
status_t DeviceHalHidl::openOutputStream(
audio_io_handle_t handle,
audio_devices_t devices,
audio_devices_t deviceType,
audio_output_flags_t flags,
struct audio_config *config,
const char *address,
sp<StreamOutHalInterface> *outStream) {
if (mDevice == 0) return NO_INIT;
DeviceAddress hidlDevice;
status_t status = deviceAddressFromHal(devices, address, &hidlDevice);
status_t status = deviceAddressFromHal(deviceType, address, &hidlDevice);
if (status != OK) return status;
AudioConfig hidlConfig;
HidlUtils::audioConfigFromHal(*config, &hidlConfig);

@ -104,7 +104,7 @@ status_t DeviceHalLocal::getInputBufferSize(
status_t DeviceHalLocal::openOutputStream(
audio_io_handle_t handle,
audio_devices_t devices,
audio_devices_t deviceType,
audio_output_flags_t flags,
struct audio_config *config,
const char *address,
@ -112,11 +112,11 @@ status_t DeviceHalLocal::openOutputStream(
audio_stream_out_t *halStream;
ALOGV("open_output_stream handle: %d devices: %x flags: %#x"
"srate: %d format %#x channels %x address %s",
handle, devices, flags,
handle, deviceType, flags,
config->sample_rate, config->format, config->channel_mask,
address);
int openResut = mDev->open_output_stream(
mDev, handle, devices, flags, config, &halStream, address);
mDev, handle, deviceType, flags, config, &halStream, address);
if (openResut == OK) {
*outStream = new StreamOutHalLocal(halStream, this);
}

@ -69,7 +69,7 @@ class DeviceHalInterface : public RefBase
// by releasing all references to the returned object.
virtual status_t openOutputStream(
audio_io_handle_t handle,
audio_devices_t devices,
audio_devices_t deviceType,
audio_output_flags_t flags,
struct audio_config *config,
const char *address,

@ -15,31 +15,6 @@ cc_library_headers {
],
}
cc_library {
name: "libmedia_helper",
vendor_available: true,
vndk: {
enabled: true,
},
double_loadable: true,
srcs: ["AudioParameter.cpp", "TypeConverter.cpp"],
cflags: [
"-Werror",
"-Wno-error=deprecated-declarations",
"-Wall",
],
shared_libs: ["libutils", "liblog"],
header_libs: [
"libmedia_headers",
"libaudioclient_headers",
"libaudio_system_headers",
],
export_header_lib_headers: [
"libmedia_headers",
],
clang: true,
}
filegroup {
name: "libmedia_omx_aidl",
srcs: [

@ -0,0 +1,29 @@
cc_library_headers {
name: "libmedia_helper_headers",
vendor_available: true,
export_include_dirs: ["include"],
}
cc_library {
name: "libmedia_helper",
vendor_available: true,
vndk: {
enabled: true,
},
double_loadable: true,
srcs: ["AudioParameter.cpp", "TypeConverter.cpp"],
cflags: [
"-Werror",
"-Wextra",
"-Wall",
],
shared_libs: ["libutils", "liblog"],
header_libs: [
"libmedia_helper_headers",
"libaudio_system_headers",
],
export_header_lib_headers: [
"libmedia_helper_headers",
],
clang: true,
}

@ -102,6 +102,10 @@ cc_library_static {
"include",
],
header_libs: [
"libmedia_helper_headers",
],
cflags: [
"-Wno-multichar",
"-Werror",

@ -34,6 +34,7 @@ cc_library_shared {
],
shared_libs: [
"libaudiofoundation",
"libaudiohal",
"libaudioprocessing",
"libaudiospdif",
@ -60,6 +61,10 @@ cc_library_shared {
"libsndfile",
],
header_libs: [
"libmedia_headers",
],
cflags: [
"-DSTATE_QUEUE_INSTANTIATIONS=\"StateQueueInstantiations.cpp\"",
"-fvisibility=hidden",

@ -381,7 +381,7 @@ static const char * const audio_interfaces[] = {
AudioHwDevice* AudioFlinger::findSuitableHwDev_l(
audio_module_handle_t module,
audio_devices_t devices)
audio_devices_t deviceType)
{
// if module is 0, the request comes from an old policy manager and we should load
// well known modules
@ -396,7 +396,7 @@ AudioHwDevice* AudioFlinger::findSuitableHwDev_l(
sp<DeviceHalInterface> dev = audioHwDevice->hwDevice();
uint32_t supportedDevices;
if (dev->getSupportedDevices(&supportedDevices) == OK &&
(supportedDevices & devices) == devices) {
(supportedDevices & deviceType) == deviceType) {
return audioHwDevice;
}
}
@ -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,
@ -2304,13 +2311,13 @@ void AudioFlinger::setAudioHwSyncForSession_l(PlaybackThread *thread, audio_sess
sp<AudioFlinger::ThreadBase> AudioFlinger::openOutput_l(audio_module_handle_t module,
audio_io_handle_t *output,
audio_config_t *config,
audio_devices_t devices,
const String8& address,
audio_output_flags_t flags)
audio_io_handle_t *output,
audio_config_t *config,
audio_devices_t deviceType,
const String8& address,
audio_output_flags_t flags)
{
AudioHwDevice *outHwDev = findSuitableHwDev_l(module, devices);
AudioHwDevice *outHwDev = findSuitableHwDev_l(module, deviceType);
if (outHwDev == NULL) {
return 0;
}
@ -2351,7 +2358,7 @@ sp<AudioFlinger::ThreadBase> AudioFlinger::openOutput_l(audio_module_handle_t mo
status_t status = outHwDev->openOutputStream(
&outputStream,
*output,
devices,
deviceType,
flags,
config,
address.string());
@ -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,
devices, 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,17 +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, devices, 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, devices, 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, devices, mSystemReady);
thread = new MixerThread(this, outputStream, *output, mSystemReady);
ALOGV("openOutput_l() created mixer output: ID %d thread %p",
*output, thread.get());
}
@ -2396,27 +2402,29 @@ sp<AudioFlinger::ThreadBase> AudioFlinger::openOutput_l(audio_module_handle_t mo
status_t AudioFlinger::openOutput(audio_module_handle_t module,
audio_io_handle_t *output,
audio_config_t *config,
audio_devices_t *devices,
const String8& address,
const sp<DeviceDescriptorBase>& device,
uint32_t *latencyMs,
audio_output_flags_t flags)
{
ALOGI("openOutput() this %p, module %d Device %#x, SamplingRate %d, Format %#08x, "
ALOGI("openOutput() this %p, module %d Device %s, SamplingRate %d, Format %#08x, "
"Channels %#x, flags %#x",
this, module,
(devices != NULL) ? *devices : 0,
device->toString().c_str(),
config->sample_rate,
config->format,
config->channel_mask,
flags);
if (devices == NULL || *devices == AUDIO_DEVICE_NONE) {
audio_devices_t deviceType = device->type();
const String8 address = String8(device->address().c_str());
if (deviceType == AUDIO_DEVICE_NONE) {
return BAD_VALUE;
}
Mutex::Autolock _l(mLock);
sp<ThreadBase> thread = openOutput_l(module, output, config, *devices, address, flags);
sp<ThreadBase> thread = openOutput_l(module, output, config, deviceType, address, flags);
if (thread != 0) {
if ((flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0) {
PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
@ -2686,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());
@ -2697,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;
@ -3119,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/LinearMap.h>
#include <media/VolumeShaper.h>
@ -175,8 +178,7 @@ public:
virtual status_t openOutput(audio_module_handle_t module,
audio_io_handle_t *output,
audio_config_t *config,
audio_devices_t *devices,
const String8& address,
const sp<DeviceDescriptorBase>& device,
uint32_t *latencyMs,
audio_output_flags_t flags);
@ -372,7 +374,7 @@ private:
virtual void onFirstRef();
AudioHwDevice* findSuitableHwDev_l(audio_module_handle_t module,
audio_devices_t devices);
audio_devices_t deviceType);
// Set kEnableExtendedChannels to true to enable greater than stereo output
// for the MixerThread and device sink. Number of channels allowed is
@ -678,11 +680,11 @@ using effect_buffer_t = int16_t;
audio_devices_t outputDevice,
const String8& outputDeviceAddress);
sp<ThreadBase> openOutput_l(audio_module_handle_t module,
audio_io_handle_t *output,
audio_config_t *config,
audio_devices_t devices,
const String8& address,
audio_output_flags_t flags);
audio_io_handle_t *output,
audio_config_t *config,
audio_devices_t deviceType,
const String8& address,
audio_output_flags_t flags);
void closeOutputFinish(const sp<PlaybackThread>& thread);
void closeInputFinish(const sp<RecordThread>& thread);
@ -717,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;
@ -751,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);

@ -34,7 +34,7 @@ namespace android {
status_t AudioHwDevice::openOutputStream(
AudioStreamOut **ppStreamOut,
audio_io_handle_t handle,
audio_devices_t devices,
audio_devices_t deviceType,
audio_output_flags_t flags,
struct audio_config *config,
const char *address)
@ -50,7 +50,7 @@ status_t AudioHwDevice::openOutputStream(
config->sample_rate,
config->format,
config->channel_mask);
status_t status = outputStream->open(handle, devices, config, address);
status_t status = outputStream->open(handle, deviceType, config, address);
if (status != NO_ERROR) {
delete outputStream;
@ -75,7 +75,7 @@ status_t AudioHwDevice::openOutputStream(
if (wrapperNeeded) {
if (SPDIFEncoder::isFormatSupported(originalConfig.format)) {
outputStream = new SpdifStreamOut(this, flags, originalConfig.format);
status = outputStream->open(handle, devices, &originalConfig, address);
status = outputStream->open(handle, deviceType, &originalConfig, address);
if (status != NO_ERROR) {
ALOGE("ERROR - openOutputStream(), SPDIF open returned %d",
status);

@ -76,7 +76,7 @@ public:
status_t openOutputStream(
AudioStreamOut **ppStreamOut,
audio_io_handle_t handle,
audio_devices_t devices,
audio_devices_t deviceType,
audio_output_flags_t flags,
struct audio_config *config,
const char *address);

@ -118,7 +118,7 @@ status_t AudioStreamOut::getPresentationPosition(uint64_t *frames, struct timesp
status_t AudioStreamOut::open(
audio_io_handle_t handle,
audio_devices_t devices,
audio_devices_t deviceType,
struct audio_config *config,
const char *address)
{
@ -130,7 +130,7 @@ status_t AudioStreamOut::open(
int status = hwDev()->openOutputStream(
handle,
devices,
deviceType,
customFlags,
config,
address,
@ -152,7 +152,7 @@ status_t AudioStreamOut::open(
status = hwDev()->openOutputStream(
handle,
devices,
deviceType,
customFlags,
&customConfig,
address,

@ -47,7 +47,7 @@ public:
virtual status_t open(
audio_io_handle_t handle,
audio_devices_t devices,
audio_devices_t deviceType,
struct audio_config *config,
const char *address);

@ -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,
@ -1792,6 +1815,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;
@ -1812,8 +1840,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,
@ -1862,8 +1889,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();

@ -17,8 +17,10 @@
#ifndef ANDROID_AUDIOPOLICY_INTERFACE_H
#define ANDROID_AUDIOPOLICY_INTERFACE_H
#include <media/AudioDeviceTypeAddr.h>
#include <media/AudioSystem.h>
#include <media/AudioPolicy.h>
#include <media/DeviceDescriptorBase.h>
#include <utils/String8.h>
namespace android {
@ -296,8 +298,7 @@ public:
virtual status_t openOutput(audio_module_handle_t module,
audio_io_handle_t *output,
audio_config_t *config,
audio_devices_t *devices,
const String8& address,
const sp<DeviceDescriptorBase>& device,
uint32_t *latencyMs,
audio_output_flags_t flags) = 0;
// creates a special output that is duplicated to the two outputs passed as arguments. The duplication is performed by

@ -22,6 +22,8 @@
#include <utils/Log.h>
#include <math.h>
#include "policy.h"
namespace android {
/**
@ -85,43 +87,14 @@ public:
*/
static audio_devices_t getDeviceForVolume(const android::DeviceTypeSet& deviceTypes)
{
audio_devices_t deviceType = AUDIO_DEVICE_NONE;
if (deviceTypes.empty()) {
// this happens when forcing a route update and no track is active on an output.
// In this case the returned category is not important.
deviceType = AUDIO_DEVICE_OUT_SPEAKER;
} else if (deviceTypes.size() > 1) {
// Multiple device selection is either:
// - speaker + one other device: give priority to speaker in this case.
// - one A2DP device + another device: happens with duplicated output. In this case
// retain the device on the A2DP output as the other must not correspond to an active
// selection if not the speaker.
// - HDMI-CEC system audio mode only output: give priority to available item in order.
if (deviceTypes.count(AUDIO_DEVICE_OUT_SPEAKER) != 0) {
deviceType = AUDIO_DEVICE_OUT_SPEAKER;
} else if (deviceTypes.count(AUDIO_DEVICE_OUT_SPEAKER_SAFE) != 0) {
deviceType = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
} else if (deviceTypes.count(AUDIO_DEVICE_OUT_HDMI_ARC) != 0) {
deviceType = AUDIO_DEVICE_OUT_HDMI_ARC;
} else if (deviceTypes.count(AUDIO_DEVICE_OUT_AUX_LINE) != 0) {
deviceType = AUDIO_DEVICE_OUT_AUX_LINE;
} else if (deviceTypes.count(AUDIO_DEVICE_OUT_SPDIF) != 0) {
deviceType = AUDIO_DEVICE_OUT_SPDIF;
} else {
std::vector<audio_devices_t> a2dpDevices = android::Intersection(
deviceTypes, android::getAudioDeviceOutAllA2dpSet());
if (a2dpDevices.size() > 1) {
ALOGW("getDeviceForVolume() invalid device combination: %s",
android::dumpDeviceTypes(deviceTypes).c_str());
}
if (!a2dpDevices.empty()) {
deviceType = a2dpDevices[0];
}
}
} else {
deviceType = *(deviceTypes.begin());
return AUDIO_DEVICE_OUT_SPEAKER;
}
audio_devices_t deviceType = apm_extract_one_audio_device(deviceTypes);
/*SPEAKER_SAFE is an alias of SPEAKER for purposes of volume control*/
if (deviceType == AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
deviceType = AUDIO_DEVICE_OUT_SPEAKER;

@ -19,6 +19,8 @@
#include <system/audio.h>
#include <vector>
#include <media/AudioContainers.h>
namespace android {
using StreamTypeVector = std::vector<audio_stream_type_t>;
@ -199,3 +201,43 @@ static inline bool hasVoiceStream(const android::StreamTypeVector &streams)
{
return hasStream(streams, AUDIO_STREAM_VOICE_CALL);
}
/**
* @brief extract one device relevant from multiple device selection
* @param deviceTypes collection of audio device type
* @return the device type that is selected
*/
static inline audio_devices_t apm_extract_one_audio_device(
const android::DeviceTypeSet& deviceTypes) {
if (deviceTypes.empty()) {
return AUDIO_DEVICE_NONE;
} else if (deviceTypes.size() == 1) {
return *(deviceTypes.begin());
} else {
// Multiple device selection is either:
// - speaker + one other device: give priority to speaker in this case.
// - one A2DP device + another device: happens with duplicated output. In this case
// retain the device on the A2DP output as the other must not correspond to an active
// selection if not the speaker.
// - HDMI-CEC system audio mode only output: give priority to available item in order.
if (deviceTypes.count(AUDIO_DEVICE_OUT_SPEAKER) != 0) {
return AUDIO_DEVICE_OUT_SPEAKER;
} else if (deviceTypes.count(AUDIO_DEVICE_OUT_SPEAKER_SAFE) != 0) {
return AUDIO_DEVICE_OUT_SPEAKER_SAFE;
} else if (deviceTypes.count(AUDIO_DEVICE_OUT_HDMI_ARC) != 0) {
return AUDIO_DEVICE_OUT_HDMI_ARC;
} else if (deviceTypes.count(AUDIO_DEVICE_OUT_AUX_LINE) != 0) {
return AUDIO_DEVICE_OUT_AUX_LINE;
} else if (deviceTypes.count(AUDIO_DEVICE_OUT_SPDIF) != 0) {
return AUDIO_DEVICE_OUT_SPDIF;
} else {
std::vector<audio_devices_t> a2dpDevices = android::Intersection(
deviceTypes, android::getAudioDeviceOutAllA2dpSet());
if (a2dpDevices.empty() || a2dpDevices.size() > 1) {
ALOGW("%s invalid device combination: %s",
__func__, android::dumpDeviceTypes(deviceTypes).c_str());
}
return a2dpDevices.empty() ? AUDIO_DEVICE_NONE : a2dpDevices[0];
}
}
}

@ -18,6 +18,7 @@
#include "DeviceDescriptor.h"
#include <utils/RefBase.h>
#include <media/AudioDeviceTypeAddr.h>
#include <media/AudioPolicy.h>
#include <utils/Vector.h>
#include <system/audio.h>

@ -130,6 +130,14 @@ public:
DeviceVector getFirstDevicesFromTypes(std::vector<audio_devices_t> orderedTypes) const;
sp<DeviceDescriptor> getFirstExistingDevice(std::vector<audio_devices_t> orderedTypes) const;
// Return device descriptor that is used to open an input/output stream.
// Null pointer will be returned if
// 1) this collection is empty
// 2) the device descriptors are not the same category(input or output)
// 3) there are more than one device type for input case
// 4) the combination of all devices is invalid for selection
sp<DeviceDescriptor> getDeviceForOpening() const;
// If there are devices with the given type and the devices to add is not empty,
// remove all the devices with the given type and add all the devices to add.
void replaceDevicesByType(audio_devices_t typeToRemove, const DeviceVector &devicesToAdd);

@ -467,8 +467,11 @@ status_t SwAudioOutputDescriptor::open(const audio_config_t *config,
audio_io_handle_t *output)
{
mDevices = devices;
const String8& address = devices.getFirstValidAddress();
DeviceTypeSet deviceTypes = devices.types();
sp<DeviceDescriptor> device = devices.getDeviceForOpening();
LOG_ALWAYS_FATAL_IF(device == nullptr,
"%s failed to get device descriptor for opening "
"with the requested devices, all device types: %s",
__func__, dumpDeviceTypes(devices.types()).c_str());
audio_config_t lConfig;
if (config == nullptr) {
@ -500,25 +503,19 @@ status_t SwAudioOutputDescriptor::open(const audio_config_t *config,
ALOGV("opening output for device %s profile %p name %s",
mDevices.toString().c_str(), mProfile.get(), mProfile->getName().c_str());
// FIXME: Stop using device types as bit mask when the interface updated.
audio_devices_t deviceType = deviceTypesToBitMask(deviceTypes);
status_t status = mClientInterface->openOutput(mProfile->getModuleHandle(),
output,
&lConfig,
&deviceType,
address,
device,
&mLatency,
mFlags);
deviceTypes = deviceTypesFromBitMask(deviceType);
LOG_ALWAYS_FATAL_IF(mDevices.types() != deviceTypes,
"%s openOutput returned device %s when given device %s",
__FUNCTION__, dumpDeviceTypes(mDevices.types()).c_str(),
dumpDeviceTypes(deviceTypes).c_str());
if (status == NO_ERROR) {
LOG_ALWAYS_FATAL_IF(*output == AUDIO_IO_HANDLE_NONE,
"%s openOutput returned output handle %d for device %s",
__FUNCTION__, *output, dumpDeviceTypes(deviceTypes).c_str());
"%s openOutput returned output handle %d for device %s, "
"selected device %s for opening",
__FUNCTION__, *output, devices.toString().c_str(),
device->toString().c_str());
mSamplingRate = lConfig.sample_rate;
mChannelMask = lConfig.channel_mask;
mFormat = lConfig.format;

@ -455,9 +455,9 @@ status_t AudioPolicyMixCollection::setUidDeviceAffinities(uid_t uid,
}
// check if this mix goes to a device in the list of devices
bool deviceMatch = false;
const AudioDeviceTypeAddr mixDevice(mix->mDeviceType, mix->mDeviceAddress.string());
for (size_t j = 0; j < devices.size(); j++) {
if (devices[j].mType == mix->mDeviceType
&& devices[j].mAddress == mix->mDeviceAddress) {
if (mixDevice.equals(devices[j])) {
deviceMatch = true;
break;
}
@ -522,7 +522,7 @@ status_t AudioPolicyMixCollection::getDevicesForUid(uid_t uid,
}
}
if (ruleAllowsUid) {
devices.add(AudioDeviceTypeAddr(mix->mDeviceType, mix->mDeviceAddress));
devices.add(AudioDeviceTypeAddr(mix->mDeviceType, mix->mDeviceAddress.string()));
}
}
return NO_ERROR;

@ -76,7 +76,7 @@ bool DeviceDescriptor::equals(const sp<DeviceDescriptor>& other) const
return false;
}
return (mDeviceType == other->mDeviceType) && (mAddress == other->mAddress) &&
return mDeviceTypeAddr.equals(other->mDeviceTypeAddr) &&
checkEqual(mEncodedFormats, other->mEncodedFormats);
}
@ -135,7 +135,7 @@ void DeviceDescriptor::toAudioPortConfig(struct audio_port_config *dstConfig,
void DeviceDescriptor::toAudioPort(struct audio_port *port) const
{
ALOGV("DeviceDescriptor::toAudioPort() handle %d type %08x", mId, mDeviceType);
ALOGV("DeviceDescriptor::toAudioPort() handle %d type %08x", mId, mDeviceTypeAddr.mType);
DeviceDescriptorBase::toAudioPort(port);
port->ext.device.hw_module = getModuleHandle();
}
@ -328,6 +328,24 @@ sp<DeviceDescriptor> DeviceVector::getFirstExistingDevice(
return device;
}
sp<DeviceDescriptor> DeviceVector::getDeviceForOpening() const
{
if (isEmpty()) {
// Return nullptr if this collection is empty.
return nullptr;
} else if (areAllOfSameDeviceType(types(), audio_is_input_device)) {
// For input case, return the first one when there is only one device.
return size() > 1 ? nullptr : *begin();
} else if (areAllOfSameDeviceType(types(), audio_is_output_device)) {
// For output case, return the device descriptor according to apm strategy.
audio_devices_t deviceType = apm_extract_one_audio_device(types());
return deviceType == AUDIO_DEVICE_NONE ? nullptr :
getDevice(deviceType, String8(""), AUDIO_FORMAT_DEFAULT);
}
// Return null pointer if the devices are not all input/output device.
return nullptr;
}
void DeviceVector::replaceDevicesByType(
audio_devices_t typeToRemove, const DeviceVector &devicesToAdd) {
DeviceVector devicesToRemove = getDevicesFromType(typeToRemove);

@ -3058,13 +3058,13 @@ status_t AudioPolicyManager::setUidDeviceAffinities(uid_t uid,
// reevaluate outputs for all given devices
for (size_t i = 0; i < devices.size(); i++) {
sp<DeviceDescriptor> devDesc = mHwModules.getDeviceDescriptor(
devices[i].mType, devices[i].mAddress, String8(),
devices[i].mType, devices[i].mAddress.c_str(), String8(),
AUDIO_FORMAT_DEFAULT);
SortedVector<audio_io_handle_t> outputs;
if (checkOutputsForDevice(devDesc, AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
outputs) != NO_ERROR) {
ALOGE("setUidDeviceAffinities() error in checkOutputsForDevice for device=%08x"
" addr=%s", devices[i].mType, devices[i].mAddress.string());
" addr=%s", devices[i].mType, devices[i].mAddress.c_str());
return INVALID_OPERATION;
}
}

@ -39,8 +39,7 @@ audio_module_handle_t AudioPolicyService::AudioPolicyClient::loadHwModule(const
status_t AudioPolicyService::AudioPolicyClient::openOutput(audio_module_handle_t module,
audio_io_handle_t *output,
audio_config_t *config,
audio_devices_t *devices,
const String8& address,
const sp<DeviceDescriptorBase>& device,
uint32_t *latencyMs,
audio_output_flags_t flags)
{
@ -49,7 +48,7 @@ status_t AudioPolicyService::AudioPolicyClient::openOutput(audio_module_handle_t
ALOGW("%s: could not get AudioFlinger", __func__);
return PERMISSION_DENIED;
}
return af->openOutput(module, output, config, devices, address, latencyMs, flags);
return af->openOutput(module, output, config, device, latencyMs, flags);
}
audio_io_handle_t AudioPolicyService::AudioPolicyClient::openDuplicateOutput(

@ -622,8 +622,7 @@ private:
virtual status_t openOutput(audio_module_handle_t module,
audio_io_handle_t *output,
audio_config_t *config,
audio_devices_t *devices,
const String8& address,
const sp<DeviceDescriptorBase>& device,
uint32_t *latencyMs,
audio_output_flags_t flags);
// creates a special output that is duplicated to the two outputs passed as arguments. The duplication is performed by

@ -34,8 +34,7 @@ public:
status_t openOutput(audio_module_handle_t module,
audio_io_handle_t *output,
audio_config_t * /*config*/,
audio_devices_t * /*devices*/,
const String8 & /*address*/,
const sp<DeviceDescriptorBase>& /*device*/,
uint32_t * /*latencyMs*/,
audio_output_flags_t /*flags*/) override {
if (module >= mNextModuleHandle) {

@ -31,8 +31,7 @@ public:
status_t openOutput(audio_module_handle_t /*module*/,
audio_io_handle_t* /*output*/,
audio_config_t* /*config*/,
audio_devices_t* /*devices*/,
const String8& /*address*/,
const sp<DeviceDescriptorBase>& /*device*/,
uint32_t* /*latencyMs*/,
audio_output_flags_t /*flags*/) override { return NO_INIT; }
audio_io_handle_t openDuplicateOutput(audio_io_handle_t /*output1*/,

Loading…
Cancel
Save