Merge changes from topic "fix-b-149854039-dynamic-hal-modules" into rvc-dev

* changes:
  Plumb the notification about audio HAL services update to APM
  libaudiohal: Allow late registration of HIDL HAL services
  Allow for late audio module discovery in APM
gugelfrei
TreeHugger Robot 4 years ago committed by Android (Google) Code Review
commit 7dfc94a0ea

@ -792,6 +792,13 @@ const sp<IAudioPolicyService> AudioSystem::get_audio_policy_service()
// ---------------------------------------------------------------------------
void AudioSystem::onNewAudioModulesAvailable()
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return;
aps->onNewAudioModulesAvailable();
}
status_t AudioSystem::setDeviceConnectionState(audio_devices_t device,
audio_policy_dev_state_t state,
const char *device_address,

@ -113,6 +113,7 @@ enum {
REMOVE_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY,
GET_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY,
GET_DEVICES_FOR_ATTRIBUTES,
AUDIO_MODULES_UPDATED, // oneway
};
#define MAX_ITEMS_PER_LIST 1024
@ -1451,6 +1452,13 @@ public:
}
return NO_ERROR;
}
virtual void onNewAudioModulesAvailable()
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
remote()->transact(AUDIO_MODULES_UPDATED, data, &reply, IBinder::FLAG_ONEWAY);
}
};
IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService");
@ -1522,7 +1530,8 @@ status_t BnAudioPolicyService::onTransact(
case REMOVE_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY:
case GET_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY:
case GET_DEVICES_FOR_ATTRIBUTES:
case SET_ALLOWED_CAPTURE_POLICY: {
case SET_ALLOWED_CAPTURE_POLICY:
case AUDIO_MODULES_UPDATED: {
if (!isServiceUid(IPCThreadState::self()->getCallingUid())) {
ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
__func__, code, IPCThreadState::self()->getCallingPid(),
@ -2672,6 +2681,12 @@ status_t BnAudioPolicyService::onTransact(
return NO_ERROR;
}
case AUDIO_MODULES_UPDATED: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
onNewAudioModulesAvailable();
return NO_ERROR;
} break;
default:
return BBinder::onTransact(code, data, reply, flags);
}

@ -221,6 +221,7 @@ public:
//
// IAudioPolicyService interface (see AudioPolicyInterface for method descriptions)
//
static void onNewAudioModulesAvailable();
static status_t setDeviceConnectionState(audio_devices_t device, audio_policy_dev_state_t state,
const char *device_address, const char *device_name,
audio_format_t encodedFormat);

@ -42,6 +42,7 @@ public:
//
// IAudioPolicyService interface (see AudioPolicyInterface for method descriptions)
//
virtual void onNewAudioModulesAvailable() = 0;
virtual status_t setDeviceConnectionState(audio_devices_t device,
audio_policy_dev_state_t state,
const char *device_address,

@ -15,12 +15,13 @@
*/
#include <string.h>
#include <vector>
#include <set>
#define LOG_TAG "DevicesFactoryHalHidl"
//#define LOG_NDEBUG 0
#include <android/hidl/manager/1.0/IServiceManager.h>
#include <android/hidl/manager/1.0/IServiceNotification.h>
#include PATH(android/hardware/audio/FILE_VERSION/IDevice.h)
#include <media/audiohal/hidl/HalDeathHandler.h>
#include <utils/Log.h>
@ -29,33 +30,57 @@
#include "DeviceHalHidl.h"
#include "DevicesFactoryHalHidl.h"
#include <set>
using ::android::hardware::audio::CPP_VERSION::IDevice;
using ::android::hardware::audio::CPP_VERSION::Result;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hidl::manager::V1_0::IServiceManager;
using ::android::hidl::manager::V1_0::IServiceNotification;
namespace android {
namespace CPP_VERSION {
DevicesFactoryHalHidl::DevicesFactoryHalHidl(sp<IDevicesFactory> devicesFactory) {
ALOG_ASSERT(devicesFactory != nullptr, "Provided IDevicesFactory service is NULL");
mDeviceFactories.push_back(devicesFactory);
if (MAJOR_VERSION >= 4) {
// The MSD factory is optional and only available starting at HAL 4.0
sp<IDevicesFactory> msdFactory{IDevicesFactory::getService(AUDIO_HAL_SERVICE_NAME_MSD)};
if (msdFactory) {
mDeviceFactories.push_back(msdFactory);
class ServiceNotificationListener : public IServiceNotification {
public:
explicit ServiceNotificationListener(sp<DevicesFactoryHalHidl> factory)
: mFactory(factory) {}
Return<void> onRegistration(const hidl_string& /*fully_qualified_name*/,
const hidl_string& instance_name,
bool /*pre_existing*/) override {
if (static_cast<std::string>(instance_name) == "default") return Void();
sp<DevicesFactoryHalHidl> factory = mFactory.promote();
if (!factory) return Void();
sp<IDevicesFactory> halFactory = IDevicesFactory::getService(instance_name);
if (halFactory) {
factory->addDeviceFactory(halFactory, true /*needToNotify*/);
}
return Void();
}
for (const auto& factory : mDeviceFactories) {
// It is assumed that the DevicesFactoryHalInterface instance is owned
// by AudioFlinger and thus have the same lifespan.
factory->linkToDeath(HalDeathHandler::getInstance(), 0 /*cookie*/);
}
private:
wp<DevicesFactoryHalHidl> mFactory;
};
DevicesFactoryHalHidl::DevicesFactoryHalHidl(sp<IDevicesFactory> devicesFactory) {
ALOG_ASSERT(devicesFactory != nullptr, "Provided default IDevicesFactory service is NULL");
addDeviceFactory(devicesFactory, false /*needToNotify*/);
}
void DevicesFactoryHalHidl::onFirstRef() {
sp<IServiceManager> sm = IServiceManager::getService();
ALOG_ASSERT(sm != nullptr, "Hardware service manager is not running");
sp<ServiceNotificationListener> listener = new ServiceNotificationListener(this);
Return<bool> result = sm->registerForNotifications(
IDevicesFactory::descriptor, "", listener);
if (result.isOk()) {
ALOGE_IF(!static_cast<bool>(result),
"Hardware service manager refused to register listener");
} else {
ALOGE("Failed to register for hardware service manager notifications: %s",
result.description().c_str());
}
}
#if MAJOR_VERSION == 2
static IDevicesFactory::Device idFromHal(const char *name, status_t* status) {
@ -83,12 +108,13 @@ static const char* idFromHal(const char *name, status_t* status) {
#endif
status_t DevicesFactoryHalHidl::openDevice(const char *name, sp<DeviceHalInterface> *device) {
if (mDeviceFactories.empty()) return NO_INIT;
auto factories = copyDeviceFactories();
if (factories.empty()) return NO_INIT;
status_t status;
auto hidlId = idFromHal(name, &status);
if (status != OK) return status;
Result retval = Result::NOT_INITIALIZED;
for (const auto& factory : mDeviceFactories) {
for (const auto& factory : factories) {
Return<void> ret = factory->openDevice(
hidlId,
[&](Result r, const sp<IDevice>& result) {
@ -113,10 +139,9 @@ status_t DevicesFactoryHalHidl::openDevice(const char *name, sp<DeviceHalInterfa
status_t DevicesFactoryHalHidl::getHalPids(std::vector<pid_t> *pids) {
std::set<pid_t> pidsSet;
for (const auto& factory : mDeviceFactories) {
auto factories = copyDeviceFactories();
for (const auto& factory : factories) {
using ::android::hidl::base::V1_0::DebugInfo;
using android::hidl::manager::V1_0::IServiceManager;
DebugInfo debugInfo;
auto ret = factory->getDebugInfo([&] (const auto &info) {
@ -135,5 +160,48 @@ status_t DevicesFactoryHalHidl::getHalPids(std::vector<pid_t> *pids) {
return NO_ERROR;
}
status_t DevicesFactoryHalHidl::setCallbackOnce(sp<DevicesFactoryHalCallback> callback) {
ALOG_ASSERT(callback != nullptr);
bool needToCallCallback = false;
{
std::lock_guard<std::mutex> lock(mLock);
if (mCallback.unsafe_get()) return INVALID_OPERATION;
mCallback = callback;
if (mHaveUndeliveredNotifications) {
needToCallCallback = true;
mHaveUndeliveredNotifications = false;
}
}
if (needToCallCallback) {
callback->onNewDevicesAvailable();
}
return NO_ERROR;
}
void DevicesFactoryHalHidl::addDeviceFactory(sp<IDevicesFactory> factory, bool needToNotify) {
// It is assumed that the DevicesFactoryHalInterface instance is owned
// by AudioFlinger and thus have the same lifespan.
factory->linkToDeath(HalDeathHandler::getInstance(), 0 /*cookie*/);
sp<DevicesFactoryHalCallback> callback;
{
std::lock_guard<std::mutex> lock(mLock);
mDeviceFactories.push_back(factory);
if (needToNotify) {
callback = mCallback.promote();
if (!callback) {
mHaveUndeliveredNotifications = true;
}
}
}
if (callback) {
callback->onNewDevicesAvailable();
}
}
std::vector<sp<IDevicesFactory>> DevicesFactoryHalHidl::copyDeviceFactories() {
std::lock_guard<std::mutex> lock(mLock);
return mDeviceFactories;
}
} // namespace CPP_VERSION
} // namespace android

@ -17,6 +17,9 @@
#ifndef ANDROID_HARDWARE_DEVICES_FACTORY_HAL_HIDL_H
#define ANDROID_HARDWARE_DEVICES_FACTORY_HAL_HIDL_H
#include <mutex>
#include <vector>
#include PATH(android/hardware/audio/FILE_VERSION/IDevicesFactory.h)
#include <media/audiohal/DevicesFactoryHalInterface.h>
#include <utils/Errors.h>
@ -32,16 +35,26 @@ namespace CPP_VERSION {
class DevicesFactoryHalHidl : public DevicesFactoryHalInterface
{
public:
DevicesFactoryHalHidl(sp<IDevicesFactory> devicesFactory);
explicit DevicesFactoryHalHidl(sp<IDevicesFactory> devicesFactory);
void onFirstRef() override;
// Opens a device with the specified name. To close the device, it is
// necessary to release references to the returned object.
virtual status_t openDevice(const char *name, sp<DeviceHalInterface> *device);
status_t openDevice(const char *name, sp<DeviceHalInterface> *device) override;
status_t getHalPids(std::vector<pid_t> *pids) override;
status_t getHalPids(std::vector<pid_t> *pids) override;
status_t setCallbackOnce(sp<DevicesFactoryHalCallback> callback) override;
private:
std::vector<sp<IDevicesFactory>> mDeviceFactories;
friend class ServiceNotificationListener;
void addDeviceFactory(sp<IDevicesFactory> factory, bool needToNotify);
std::vector<sp<IDevicesFactory>> copyDeviceFactories();
std::mutex mLock;
std::vector<sp<IDevicesFactory>> mDeviceFactories; // GUARDED_BY(mLock)
wp<DevicesFactoryHalCallback> mCallback; // GUARDED_BY(mLock)
bool mHaveUndeliveredNotifications = false; // GUARDED_BY(mLock)
virtual ~DevicesFactoryHalHidl() = default;
};

@ -44,6 +44,13 @@ status_t DevicesFactoryHalHybrid::getHalPids(std::vector<pid_t> *pids) {
return INVALID_OPERATION;
}
status_t DevicesFactoryHalHybrid::setCallbackOnce(sp<DevicesFactoryHalCallback> callback) {
if (mHidlFactory) {
return mHidlFactory->setCallbackOnce(callback);
}
return INVALID_OPERATION;
}
} // namespace CPP_VERSION
extern "C" __attribute__((visibility("default"))) void* createIDevicesFactory() {

@ -38,6 +38,8 @@ class DevicesFactoryHalHybrid : public DevicesFactoryHalInterface
status_t getHalPids(std::vector<pid_t> *pids) override;
status_t setCallbackOnce(sp<DevicesFactoryHalCallback> callback) override;
private:
sp<DevicesFactoryHalInterface> mLocalFactory;
sp<DevicesFactoryHalInterface> mHidlFactory;

@ -37,6 +37,10 @@ class DevicesFactoryHalLocal : public DevicesFactoryHalInterface
return INVALID_OPERATION;
}
status_t setCallbackOnce(sp<DevicesFactoryHalCallback> callback __unused) override {
return INVALID_OPERATION;
}
private:
friend class DevicesFactoryHalHybrid;

@ -24,6 +24,12 @@
namespace android {
class DevicesFactoryHalCallback : public RefBase
{
public:
virtual void onNewDevicesAvailable() = 0;
};
class DevicesFactoryHalInterface : public RefBase
{
public:
@ -33,6 +39,10 @@ class DevicesFactoryHalInterface : public RefBase
virtual status_t getHalPids(std::vector<pid_t> *pids) = 0;
// Sets a DevicesFactoryHalCallback to notify the client.
// The callback can be only set once.
virtual status_t setCallbackOnce(sp<DevicesFactoryHalCallback> callback) = 0;
static sp<DevicesFactoryHalInterface> create();
protected:

@ -29,6 +29,7 @@
#include <string>
#include <sys/time.h>
#include <sys/resource.h>
#include <thread>
#include <android/os/IExternalVibratorService.h>
#include <binder/IPCThreadState.h>
@ -144,6 +145,19 @@ static sp<os::IExternalVibratorService> getExternalVibratorService() {
return sExternalVibratorService;
}
class DevicesFactoryHalCallbackImpl : public DevicesFactoryHalCallback {
public:
void onNewDevicesAvailable() override {
// Start a detached thread to execute notification in parallel.
// This is done to prevent mutual blocking of audio_flinger and
// audio_policy services during system initialization.
std::thread notifier([]() {
AudioSystem::onNewAudioModulesAvailable();
});
notifier.detach();
}
};
// ----------------------------------------------------------------------------
std::string formatToString(audio_format_t format) {
@ -227,6 +241,9 @@ void AudioFlinger::onFirstRef()
mMode = AUDIO_MODE_NORMAL;
gAudioFlinger = this;
mDevicesFactoryHalCallback = new DevicesFactoryHalCallbackImpl;
mDevicesFactoryHal->setCallbackOnce(mDevicesFactoryHalCallback);
}
status_t AudioFlinger::setAudioHalPids(const std::vector<pid_t>& pids) {

@ -105,6 +105,7 @@ class AudioMixer;
class AudioBuffer;
class AudioResampler;
class DeviceHalInterface;
class DevicesFactoryHalCallback;
class DevicesFactoryHalInterface;
class EffectsFactoryHalInterface;
class FastMixer;
@ -837,6 +838,7 @@ using effect_buffer_t = int16_t;
DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*> mAudioHwDevs;
sp<DevicesFactoryHalInterface> mDevicesFactoryHal;
sp<DevicesFactoryHalCallback> mDevicesFactoryHalCallback;
// for dump, indicates which hardware operation is currently in progress (but not stream ops)
enum hardware_call_state {

@ -83,6 +83,10 @@ public:
// configuration functions
//
// Informs APM that new HAL modules are available. This typically happens
// due to registration of an audio HAL service.
virtual void onNewAudioModulesAvailable() = 0;
// indicate a change in device connection status
virtual status_t setDeviceConnectionState(audio_devices_t device,
audio_policy_dev_state_t state,

@ -37,13 +37,13 @@ class AudioPolicyConfig
{
public:
AudioPolicyConfig(HwModuleCollection &hwModules,
DeviceVector &availableOutputDevices,
DeviceVector &availableInputDevices,
DeviceVector &outputDevices,
DeviceVector &inputDevices,
sp<DeviceDescriptor> &defaultOutputDevice)
: mEngineLibraryNameSuffix(kDefaultEngineLibraryNameSuffix),
mHwModules(hwModules),
mAvailableOutputDevices(availableOutputDevices),
mAvailableInputDevices(availableInputDevices),
mOutputDevices(outputDevices),
mInputDevices(inputDevices),
mDefaultOutputDevice(defaultOutputDevice),
mIsSpeakerDrcEnabled(false),
mIsCallScreenModeSupported(false)
@ -70,23 +70,23 @@ public:
mHwModules = hwModules;
}
void addAvailableDevice(const sp<DeviceDescriptor> &availableDevice)
void addDevice(const sp<DeviceDescriptor> &device)
{
if (audio_is_output_device(availableDevice->type())) {
mAvailableOutputDevices.add(availableDevice);
} else if (audio_is_input_device(availableDevice->type())) {
mAvailableInputDevices.add(availableDevice);
if (audio_is_output_device(device->type())) {
mOutputDevices.add(device);
} else if (audio_is_input_device(device->type())) {
mInputDevices.add(device);
}
}
void addAvailableInputDevices(const DeviceVector &availableInputDevices)
void addInputDevices(const DeviceVector &inputDevices)
{
mAvailableInputDevices.add(availableInputDevices);
mInputDevices.add(inputDevices);
}
void addAvailableOutputDevices(const DeviceVector &availableOutputDevices)
void addOutputDevices(const DeviceVector &outputDevices)
{
mAvailableOutputDevices.add(availableOutputDevices);
mOutputDevices.add(outputDevices);
}
bool isSpeakerDrcEnabled() const { return mIsSpeakerDrcEnabled; }
@ -106,14 +106,14 @@ public:
const HwModuleCollection getHwModules() const { return mHwModules; }
const DeviceVector &getAvailableInputDevices() const
const DeviceVector &getInputDevices() const
{
return mAvailableInputDevices;
return mInputDevices;
}
const DeviceVector &getAvailableOutputDevices() const
const DeviceVector &getOutputDevices() const
{
return mAvailableOutputDevices;
return mOutputDevices;
}
void setDefaultOutputDevice(const sp<DeviceDescriptor> &defaultDevice)
@ -134,13 +134,11 @@ public:
sp<AudioProfile> micProfile = new AudioProfile(
AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_MONO, 8000);
defaultInputDevice->addAudioProfile(micProfile);
mAvailableOutputDevices.add(mDefaultOutputDevice);
mAvailableInputDevices.add(defaultInputDevice);
mOutputDevices.add(mDefaultOutputDevice);
mInputDevices.add(defaultInputDevice);
sp<HwModule> module = new HwModule(AUDIO_HARDWARE_MODULE_ID_PRIMARY, 2 /*halVersionMajor*/);
mHwModules.add(module);
mDefaultOutputDevice->attach(module);
defaultInputDevice->attach(module);
sp<OutputProfile> outProfile = new OutputProfile("primary");
outProfile->addAudioProfile(
@ -191,8 +189,8 @@ private:
std::string mSource;
std::string mEngineLibraryNameSuffix;
HwModuleCollection &mHwModules; /**< Collection of Module, with Profiles, i.e. Mix Ports. */
DeviceVector &mAvailableOutputDevices;
DeviceVector &mAvailableInputDevices;
DeviceVector &mOutputDevices;
DeviceVector &mInputDevices;
sp<DeviceDescriptor> &mDefaultOutputDevice;
// TODO: remove when legacy conf file is removed. true on devices that use DRC on the
// DEVICE_CATEGORY_SPEAKER path to boost soft sounds, used to adjust volume curves accordingly.

@ -653,7 +653,7 @@ Return<ModuleTraits::Element> ModuleTraits::deserialize(const xmlNode *cur, PtrS
sp<DeviceDescriptor> device = module->getDeclaredDevices().
getDeviceFromTagName(std::string(reinterpret_cast<const char*>(
attachedDevice.get())));
ctx->addAvailableDevice(device);
ctx->addDevice(device);
}
}
}

@ -4397,7 +4397,7 @@ AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterfa
mpClientInterface(clientInterface),
mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
mA2dpSuspended(false),
mConfig(mHwModulesAll, mAvailableOutputDevices, mAvailableInputDevices, mDefaultOutputDevice),
mConfig(mHwModulesAll, mOutputDevicesAll, mInputDevicesAll, mDefaultOutputDevice),
mAudioPortGeneration(1),
mBeaconMuteRefCount(0),
mBeaconPlayingRefCount(0),
@ -4442,9 +4442,69 @@ status_t AudioPolicyManager::initialize() {
return status;
}
// mAvailableOutputDevices and mAvailableInputDevices now contain all attached devices
// after parsing the config, mOutputDevicesAll and mInputDevicesAll contain all known devices;
// open all output streams needed to access attached devices
onNewAudioModulesAvailable();
// make sure default device is reachable
if (mDefaultOutputDevice == 0 || !mAvailableOutputDevices.contains(mDefaultOutputDevice)) {
ALOGE_IF(mDefaultOutputDevice != 0, "Default device %s is unreachable",
mDefaultOutputDevice->toString().c_str());
status = NO_INIT;
}
// If microphones address is empty, set it according to device type
for (size_t i = 0; i < mAvailableInputDevices.size(); i++) {
if (mAvailableInputDevices[i]->address().empty()) {
if (mAvailableInputDevices[i]->type() == AUDIO_DEVICE_IN_BUILTIN_MIC) {
mAvailableInputDevices[i]->setAddress(AUDIO_BOTTOM_MICROPHONE_ADDRESS);
} else if (mAvailableInputDevices[i]->type() == AUDIO_DEVICE_IN_BACK_MIC) {
mAvailableInputDevices[i]->setAddress(AUDIO_BACK_MICROPHONE_ADDRESS);
}
}
}
if (mPrimaryOutput == 0) {
ALOGE("Failed to open primary output");
status = NO_INIT;
}
// Silence ALOGV statements
property_set("log.tag." LOG_TAG, "D");
updateDevicesAndOutputs();
return status;
}
AudioPolicyManager::~AudioPolicyManager()
{
for (size_t i = 0; i < mOutputs.size(); i++) {
mOutputs.valueAt(i)->close();
}
for (size_t i = 0; i < mInputs.size(); i++) {
mInputs.valueAt(i)->close();
}
mAvailableOutputDevices.clear();
mAvailableInputDevices.clear();
mOutputs.clear();
mInputs.clear();
mHwModules.clear();
mHwModulesAll.clear();
mManualSurroundFormats.clear();
}
status_t AudioPolicyManager::initCheck()
{
return hasPrimaryOutput() ? NO_ERROR : NO_INIT;
}
// ---
void AudioPolicyManager::onNewAudioModulesAvailable()
{
for (const auto& hwModule : mHwModulesAll) {
if (std::find(mHwModules.begin(), mHwModules.end(), hwModule) != mHwModules.end()) {
continue;
}
hwModule->setHandle(mpClientInterface->loadHwModule(hwModule->getName()));
if (hwModule->getHandle() == AUDIO_MODULE_HANDLE_NONE) {
ALOGW("could not open HW module %s", hwModule->getName());
@ -4473,7 +4533,7 @@ status_t AudioPolicyManager::initialize() {
continue;
}
const DeviceVector &supportedDevices = outProfile->getSupportedDevices();
DeviceVector availProfileDevices = supportedDevices.filter(mAvailableOutputDevices);
DeviceVector availProfileDevices = supportedDevices.filter(mOutputDevicesAll);
sp<DeviceDescriptor> supportedDevice = 0;
if (supportedDevices.contains(mDefaultOutputDevice)) {
supportedDevice = mDefaultOutputDevice;
@ -4485,7 +4545,7 @@ status_t AudioPolicyManager::initialize() {
}
supportedDevice = availProfileDevices.itemAt(0);
}
if (!mAvailableOutputDevices.contains(supportedDevice)) {
if (!mOutputDevicesAll.contains(supportedDevice)) {
continue;
}
sp<SwAudioOutputDescriptor> outputDesc = new SwAudioOutputDescriptor(outProfile,
@ -4503,6 +4563,8 @@ status_t AudioPolicyManager::initialize() {
// give a valid ID to an attached device once confirmed it is reachable
if (!device->isAttached()) {
device->attach(hwModule);
mAvailableOutputDevices.add(device);
setEngineDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
}
}
if (mPrimaryOutput == 0 &&
@ -4531,7 +4593,7 @@ status_t AudioPolicyManager::initialize() {
// chose first device present in profile's SupportedDevices also part of
// available input devices
const DeviceVector &supportedDevices = inProfile->getSupportedDevices();
DeviceVector availProfileDevices = supportedDevices.filter(mAvailableInputDevices);
DeviceVector availProfileDevices = supportedDevices.filter(mInputDevicesAll);
if (availProfileDevices.isEmpty()) {
ALOGE("%s: Input device list is empty!", __FUNCTION__);
continue;
@ -4556,81 +4618,15 @@ status_t AudioPolicyManager::initialize() {
if (!device->isAttached()) {
device->attach(hwModule);
device->importAudioPortAndPickAudioProfile(inProfile, true);
mAvailableInputDevices.add(device);
setEngineDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
}
}
inputDesc->close();
}
}
// make sure all attached devices have been allocated a unique ID
auto checkAndSetAvailable = [this](auto& devices) {
for (size_t i = 0; i < devices.size();) {
const auto &device = devices[i];
if (!device->isAttached()) {
ALOGW("device %s is unreachable", device->toString().c_str());
devices.remove(device);
continue;
}
// Device is now validated and can be appended to the available devices of the engine
setEngineDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
i++;
}
};
checkAndSetAvailable(mAvailableOutputDevices);
checkAndSetAvailable(mAvailableInputDevices);
// make sure default device is reachable
if (mDefaultOutputDevice == 0 || !mAvailableOutputDevices.contains(mDefaultOutputDevice)) {
ALOGE_IF(mDefaultOutputDevice != 0, "Default device %s is unreachable",
mDefaultOutputDevice->toString().c_str());
status = NO_INIT;
}
// If microphones address is empty, set it according to device type
for (size_t i = 0; i < mAvailableInputDevices.size(); i++) {
if (mAvailableInputDevices[i]->address().empty()) {
if (mAvailableInputDevices[i]->type() == AUDIO_DEVICE_IN_BUILTIN_MIC) {
mAvailableInputDevices[i]->setAddress(AUDIO_BOTTOM_MICROPHONE_ADDRESS);
} else if (mAvailableInputDevices[i]->type() == AUDIO_DEVICE_IN_BACK_MIC) {
mAvailableInputDevices[i]->setAddress(AUDIO_BACK_MICROPHONE_ADDRESS);
}
}
}
if (mPrimaryOutput == 0) {
ALOGE("Failed to open primary output");
status = NO_INIT;
}
// Silence ALOGV statements
property_set("log.tag." LOG_TAG, "D");
updateDevicesAndOutputs();
return status;
}
AudioPolicyManager::~AudioPolicyManager()
{
for (size_t i = 0; i < mOutputs.size(); i++) {
mOutputs.valueAt(i)->close();
}
for (size_t i = 0; i < mInputs.size(); i++) {
mInputs.valueAt(i)->close();
}
mAvailableOutputDevices.clear();
mAvailableInputDevices.clear();
mOutputs.clear();
mInputs.clear();
mHwModules.clear();
mHwModulesAll.clear();
mManualSurroundFormats.clear();
}
status_t AudioPolicyManager::initCheck()
{
return hasPrimaryOutput() ? NO_ERROR : NO_INIT;
}
// ---
void AudioPolicyManager::addOutput(audio_io_handle_t output,
const sp<SwAudioOutputDescriptor>& outputDesc)
{

@ -325,6 +325,8 @@ public:
bool isCallScreenModeSupported() override;
void onNewAudioModulesAvailable() override;
status_t initialize();
protected:
@ -729,6 +731,8 @@ protected:
SwAudioOutputCollection mPreviousOutputs;
AudioInputCollection mInputs; // list of input descriptors
DeviceVector mOutputDevicesAll; // all output devices from the config
DeviceVector mInputDevicesAll; // all input devices from the config
DeviceVector mAvailableOutputDevices; // all available output devices
DeviceVector mAvailableInputDevices; // all available input devices
@ -739,9 +743,8 @@ protected:
EffectDescriptorCollection mEffects; // list of registered audio effects
sp<DeviceDescriptor> mDefaultOutputDevice; // output device selected by default at boot time
HwModuleCollection mHwModules; // contains only modules that have been loaded successfully
HwModuleCollection mHwModulesAll; // normally not needed, used during construction and for
// dumps
HwModuleCollection mHwModules; // contains modules that have been loaded successfully
HwModuleCollection mHwModulesAll; // contains all modules declared in the config
AudioPolicyConfig mConfig;

@ -66,6 +66,14 @@ status_t AudioPolicyService::validateUsage(audio_usage_t usage, pid_t pid, uid_t
// ----------------------------------------------------------------------------
void AudioPolicyService::doOnNewAudioModulesAvailable()
{
if (mAudioPolicyManager == NULL) return;
Mutex::Autolock _l(mLock);
AutoCallerClear acc;
mAudioPolicyManager->onNewAudioModulesAvailable();
}
status_t AudioPolicyService::setDeviceConnectionState(audio_devices_t device,
audio_policy_dev_state_t state,
const char *device_address,

@ -1321,6 +1321,16 @@ bool AudioPolicyService::AudioCommandThread::threadLoop()
mLock.lock();
}
} break;
case AUDIO_MODULES_UPDATE: {
ALOGV("AudioCommandThread() processing audio modules update");
svc = mService.promote();
if (svc == 0) {
break;
}
mLock.unlock();
svc->doOnNewAudioModulesAvailable();
mLock.lock();
} break;
default:
ALOGW("AudioCommandThread() unknown command %d", command->mCommand);
@ -1610,6 +1620,13 @@ void AudioPolicyService::AudioCommandThread::recordingConfigurationUpdateCommand
sendCommand(command);
}
void AudioPolicyService::AudioCommandThread::audioModulesUpdateCommand()
{
sp<AudioCommand> command = new AudioCommand();
command->mCommand = AUDIO_MODULES_UPDATE;
sendCommand(command);
}
status_t AudioPolicyService::AudioCommandThread::sendCommand(sp<AudioCommand>& command, int delayMs)
{
{
@ -1857,6 +1874,11 @@ void AudioPolicyService::setEffectSuspended(int effectId,
mAudioCommandThread->setEffectSuspendedCommand(effectId, sessionId, suspended);
}
void AudioPolicyService::onNewAudioModulesAvailable()
{
mAudioCommandThread->audioModulesUpdateCommand();
}
extern "C" {
audio_module_handle_t aps_load_hw_module(void *service __unused,

@ -60,6 +60,7 @@ public:
// BnAudioPolicyService (see AudioPolicyInterface for method descriptions)
//
void onNewAudioModulesAvailable() override;
virtual status_t setDeviceConnectionState(audio_devices_t device,
audio_policy_dev_state_t state,
const char *device_address,
@ -277,6 +278,7 @@ public:
bool isCallScreenModeSupported() override;
void doOnNewAudioModulesAvailable();
status_t doStopOutput(audio_port_handle_t portId);
void doReleaseOutput(audio_port_handle_t portId);
@ -463,6 +465,7 @@ private:
DYN_POLICY_MIX_STATE_UPDATE,
RECORDING_CONFIGURATION_UPDATE,
SET_EFFECT_SUSPENDED,
AUDIO_MODULES_UPDATE,
};
AudioCommandThread (String8 name, const wp<AudioPolicyService>& service);
@ -508,6 +511,7 @@ private:
void setEffectSuspendedCommand(int effectId,
audio_session_t sessionId,
bool suspended);
void audioModulesUpdateCommand();
void insertCommand_l(AudioCommand *command, int delayMs = 0);
private:
class AudioCommandData;

@ -15,6 +15,7 @@
*/
#include <map>
#include <set>
#include <system/audio.h>
#include <utils/Log.h>
@ -27,7 +28,10 @@ namespace android {
class AudioPolicyManagerTestClient : public AudioPolicyTestClient {
public:
// AudioPolicyClientInterface implementation
audio_module_handle_t loadHwModule(const char * /*name*/) override {
audio_module_handle_t loadHwModule(const char* name) override {
if (!mAllowedModuleNames.empty() && !mAllowedModuleNames.count(name)) {
return AUDIO_MODULE_HANDLE_NONE;
}
return mNextModuleHandle++;
}
@ -101,11 +105,18 @@ public:
return &it->second;
};
audio_module_handle_t peekNextModuleHandle() const { return mNextModuleHandle; }
void swapAllowedModuleNames(std::set<std::string>&& names = {}) {
mAllowedModuleNames.swap(names);
}
private:
audio_module_handle_t mNextModuleHandle = AUDIO_MODULE_HANDLE_NONE + 1;
audio_io_handle_t mNextIoHandle = AUDIO_IO_HANDLE_NONE + 1;
audio_patch_handle_t mNextPatchHandle = AUDIO_PATCH_HANDLE_NONE + 1;
std::map<audio_patch_handle_t, struct audio_patch> mActivePatches;
std::set<std::string> mAllowedModuleNames;
};
} // namespace android

@ -27,6 +27,8 @@ class AudioPolicyTestManager : public AudioPolicyManager {
using AudioPolicyManager::loadConfig;
using AudioPolicyManager::initialize;
using AudioPolicyManager::getOutputs;
using AudioPolicyManager::getAvailableOutputDevices;
using AudioPolicyManager::getAvailableInputDevices;
};
} // namespace android

@ -67,10 +67,10 @@ TEST(AudioHealthTest, AttachedDeviceFound) {
manager.loadConfig();
ASSERT_NE("AudioPolicyConfig::setDefault", manager.getConfig().getSource());
for (auto desc : manager.getConfig().getAvailableInputDevices()) {
for (auto desc : manager.getConfig().getInputDevices()) {
ASSERT_NE(attachedDevices.end(), attachedDevices.find(desc->type()));
}
for (auto desc : manager.getConfig().getAvailableOutputDevices()) {
for (auto desc : manager.getConfig().getOutputDevices()) {
ASSERT_NE(attachedDevices.end(), attachedDevices.find(desc->type()));
}
}

@ -298,9 +298,9 @@ TEST_F(AudioPolicyManagerTest, CreateAudioPatchFromMix) {
audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE;
uid_t uid = 42;
const PatchCountCheck patchCount = snapshotPatchCount();
ASSERT_FALSE(mManager->getConfig().getAvailableInputDevices().isEmpty());
ASSERT_FALSE(mManager->getAvailableInputDevices().isEmpty());
PatchBuilder patchBuilder;
patchBuilder.addSource(mManager->getConfig().getAvailableInputDevices()[0]).
patchBuilder.addSource(mManager->getAvailableInputDevices()[0]).
addSink(mManager->getConfig().getDefaultOutputDevice());
ASSERT_EQ(NO_ERROR, mManager->createAudioPatch(patchBuilder.patch(), &handle, uid));
ASSERT_NE(AUDIO_PATCH_HANDLE_NONE, handle);
@ -334,15 +334,13 @@ void AudioPolicyManagerTestMsd::SetUpManagerConfig() {
sp<AudioProfile> pcmInputProfile = new AudioProfile(
AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO, 44100);
mMsdInputDevice->addAudioProfile(pcmInputProfile);
config.addAvailableDevice(mMsdOutputDevice);
config.addAvailableDevice(mMsdInputDevice);
config.addDevice(mMsdOutputDevice);
config.addDevice(mMsdInputDevice);
sp<HwModule> msdModule = new HwModule(AUDIO_HARDWARE_MODULE_ID_MSD, 2 /*halVersionMajor*/);
HwModuleCollection modules = config.getHwModules();
modules.add(msdModule);
config.setHwModules(modules);
mMsdOutputDevice->attach(msdModule);
mMsdInputDevice->attach(msdModule);
sp<OutputProfile> msdOutputProfile = new OutputProfile("msd input");
msdOutputProfile->addAudioProfile(pcmOutputProfile);
@ -1127,3 +1125,40 @@ TEST_F(AudioPolicyManagerTVTest, MatchOutputDirectMMapNoIrq) {
AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_MMAP_NOIRQ),
"low latency");
}
class AudioPolicyManagerDynamicHwModulesTest : public AudioPolicyManagerTestWithConfigurationFile {
protected:
void SetUpManagerConfig() override;
};
void AudioPolicyManagerDynamicHwModulesTest::SetUpManagerConfig() {
AudioPolicyManagerTestWithConfigurationFile::SetUpManagerConfig();
// Only allow successful opening of "primary" hw module during APM initialization.
mClient->swapAllowedModuleNames({"primary"});
}
TEST_F(AudioPolicyManagerDynamicHwModulesTest, InitSuccess) {
// SetUp must finish with no assertions.
}
TEST_F(AudioPolicyManagerDynamicHwModulesTest, DynamicAddition) {
const auto handleBefore = mClient->peekNextModuleHandle();
mManager->onNewAudioModulesAvailable();
ASSERT_EQ(handleBefore, mClient->peekNextModuleHandle());
// Reset module loading restrictions.
mClient->swapAllowedModuleNames();
mManager->onNewAudioModulesAvailable();
const auto handleAfter = mClient->peekNextModuleHandle();
ASSERT_GT(handleAfter, handleBefore);
mManager->onNewAudioModulesAvailable();
ASSERT_EQ(handleAfter, mClient->peekNextModuleHandle());
}
TEST_F(AudioPolicyManagerDynamicHwModulesTest, AddedDeviceAvailable) {
ASSERT_EQ(AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, mManager->getDeviceConnectionState(
AUDIO_DEVICE_IN_REMOTE_SUBMIX, "0"));
mClient->swapAllowedModuleNames({"primary", "r_submix"});
mManager->onNewAudioModulesAvailable();
ASSERT_EQ(AUDIO_POLICY_DEVICE_STATE_AVAILABLE, mManager->getDeviceConnectionState(
AUDIO_DEVICE_IN_REMOTE_SUBMIX, "0"));
}

Loading…
Cancel
Save