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, status_t AudioSystem::setDeviceConnectionState(audio_devices_t device,
audio_policy_dev_state_t state, audio_policy_dev_state_t state,
const char *device_address, const char *device_address,

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

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

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

@ -15,12 +15,13 @@
*/ */
#include <string.h> #include <string.h>
#include <vector> #include <set>
#define LOG_TAG "DevicesFactoryHalHidl" #define LOG_TAG "DevicesFactoryHalHidl"
//#define LOG_NDEBUG 0 //#define LOG_NDEBUG 0
#include <android/hidl/manager/1.0/IServiceManager.h> #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 PATH(android/hardware/audio/FILE_VERSION/IDevice.h)
#include <media/audiohal/hidl/HalDeathHandler.h> #include <media/audiohal/hidl/HalDeathHandler.h>
#include <utils/Log.h> #include <utils/Log.h>
@ -29,33 +30,57 @@
#include "DeviceHalHidl.h" #include "DeviceHalHidl.h"
#include "DevicesFactoryHalHidl.h" #include "DevicesFactoryHalHidl.h"
#include <set>
using ::android::hardware::audio::CPP_VERSION::IDevice; using ::android::hardware::audio::CPP_VERSION::IDevice;
using ::android::hardware::audio::CPP_VERSION::Result; using ::android::hardware::audio::CPP_VERSION::Result;
using ::android::hardware::Return; 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 android {
namespace CPP_VERSION { namespace CPP_VERSION {
DevicesFactoryHalHidl::DevicesFactoryHalHidl(sp<IDevicesFactory> devicesFactory) { class ServiceNotificationListener : public IServiceNotification {
ALOG_ASSERT(devicesFactory != nullptr, "Provided IDevicesFactory service is NULL"); public:
explicit ServiceNotificationListener(sp<DevicesFactoryHalHidl> factory)
mDeviceFactories.push_back(devicesFactory); : mFactory(factory) {}
if (MAJOR_VERSION >= 4) {
// The MSD factory is optional and only available starting at HAL 4.0 Return<void> onRegistration(const hidl_string& /*fully_qualified_name*/,
sp<IDevicesFactory> msdFactory{IDevicesFactory::getService(AUDIO_HAL_SERVICE_NAME_MSD)}; const hidl_string& instance_name,
if (msdFactory) { bool /*pre_existing*/) override {
mDeviceFactories.push_back(msdFactory); 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 private:
// by AudioFlinger and thus have the same lifespan. wp<DevicesFactoryHalHidl> mFactory;
factory->linkToDeath(HalDeathHandler::getInstance(), 0 /*cookie*/); };
}
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 #if MAJOR_VERSION == 2
static IDevicesFactory::Device idFromHal(const char *name, status_t* status) { 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 #endif
status_t DevicesFactoryHalHidl::openDevice(const char *name, sp<DeviceHalInterface> *device) { 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; status_t status;
auto hidlId = idFromHal(name, &status); auto hidlId = idFromHal(name, &status);
if (status != OK) return status; if (status != OK) return status;
Result retval = Result::NOT_INITIALIZED; Result retval = Result::NOT_INITIALIZED;
for (const auto& factory : mDeviceFactories) { for (const auto& factory : factories) {
Return<void> ret = factory->openDevice( Return<void> ret = factory->openDevice(
hidlId, hidlId,
[&](Result r, const sp<IDevice>& result) { [&](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) { status_t DevicesFactoryHalHidl::getHalPids(std::vector<pid_t> *pids) {
std::set<pid_t> pidsSet; std::set<pid_t> pidsSet;
auto factories = copyDeviceFactories();
for (const auto& factory : mDeviceFactories) { for (const auto& factory : factories) {
using ::android::hidl::base::V1_0::DebugInfo; using ::android::hidl::base::V1_0::DebugInfo;
using android::hidl::manager::V1_0::IServiceManager;
DebugInfo debugInfo; DebugInfo debugInfo;
auto ret = factory->getDebugInfo([&] (const auto &info) { auto ret = factory->getDebugInfo([&] (const auto &info) {
@ -135,5 +160,48 @@ status_t DevicesFactoryHalHidl::getHalPids(std::vector<pid_t> *pids) {
return NO_ERROR; 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 CPP_VERSION
} // namespace android } // namespace android

@ -17,6 +17,9 @@
#ifndef ANDROID_HARDWARE_DEVICES_FACTORY_HAL_HIDL_H #ifndef ANDROID_HARDWARE_DEVICES_FACTORY_HAL_HIDL_H
#define 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 PATH(android/hardware/audio/FILE_VERSION/IDevicesFactory.h)
#include <media/audiohal/DevicesFactoryHalInterface.h> #include <media/audiohal/DevicesFactoryHalInterface.h>
#include <utils/Errors.h> #include <utils/Errors.h>
@ -32,16 +35,26 @@ namespace CPP_VERSION {
class DevicesFactoryHalHidl : public DevicesFactoryHalInterface class DevicesFactoryHalHidl : public DevicesFactoryHalInterface
{ {
public: 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 // Opens a device with the specified name. To close the device, it is
// necessary to release references to the returned object. // 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: 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; virtual ~DevicesFactoryHalHidl() = default;
}; };

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

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

@ -24,6 +24,12 @@
namespace android { namespace android {
class DevicesFactoryHalCallback : public RefBase
{
public:
virtual void onNewDevicesAvailable() = 0;
};
class DevicesFactoryHalInterface : public RefBase class DevicesFactoryHalInterface : public RefBase
{ {
public: public:
@ -33,6 +39,10 @@ class DevicesFactoryHalInterface : public RefBase
virtual status_t getHalPids(std::vector<pid_t> *pids) = 0; 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(); static sp<DevicesFactoryHalInterface> create();
protected: protected:

@ -29,6 +29,7 @@
#include <string> #include <string>
#include <sys/time.h> #include <sys/time.h>
#include <sys/resource.h> #include <sys/resource.h>
#include <thread>
#include <android/os/IExternalVibratorService.h> #include <android/os/IExternalVibratorService.h>
#include <binder/IPCThreadState.h> #include <binder/IPCThreadState.h>
@ -144,6 +145,19 @@ static sp<os::IExternalVibratorService> getExternalVibratorService() {
return sExternalVibratorService; 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) { std::string formatToString(audio_format_t format) {
@ -227,6 +241,9 @@ void AudioFlinger::onFirstRef()
mMode = AUDIO_MODE_NORMAL; mMode = AUDIO_MODE_NORMAL;
gAudioFlinger = this; gAudioFlinger = this;
mDevicesFactoryHalCallback = new DevicesFactoryHalCallbackImpl;
mDevicesFactoryHal->setCallbackOnce(mDevicesFactoryHalCallback);
} }
status_t AudioFlinger::setAudioHalPids(const std::vector<pid_t>& pids) { status_t AudioFlinger::setAudioHalPids(const std::vector<pid_t>& pids) {

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

@ -83,6 +83,10 @@ public:
// configuration functions // 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 // indicate a change in device connection status
virtual status_t setDeviceConnectionState(audio_devices_t device, virtual status_t setDeviceConnectionState(audio_devices_t device,
audio_policy_dev_state_t state, audio_policy_dev_state_t state,

@ -37,13 +37,13 @@ class AudioPolicyConfig
{ {
public: public:
AudioPolicyConfig(HwModuleCollection &hwModules, AudioPolicyConfig(HwModuleCollection &hwModules,
DeviceVector &availableOutputDevices, DeviceVector &outputDevices,
DeviceVector &availableInputDevices, DeviceVector &inputDevices,
sp<DeviceDescriptor> &defaultOutputDevice) sp<DeviceDescriptor> &defaultOutputDevice)
: mEngineLibraryNameSuffix(kDefaultEngineLibraryNameSuffix), : mEngineLibraryNameSuffix(kDefaultEngineLibraryNameSuffix),
mHwModules(hwModules), mHwModules(hwModules),
mAvailableOutputDevices(availableOutputDevices), mOutputDevices(outputDevices),
mAvailableInputDevices(availableInputDevices), mInputDevices(inputDevices),
mDefaultOutputDevice(defaultOutputDevice), mDefaultOutputDevice(defaultOutputDevice),
mIsSpeakerDrcEnabled(false), mIsSpeakerDrcEnabled(false),
mIsCallScreenModeSupported(false) mIsCallScreenModeSupported(false)
@ -70,23 +70,23 @@ public:
mHwModules = hwModules; mHwModules = hwModules;
} }
void addAvailableDevice(const sp<DeviceDescriptor> &availableDevice) void addDevice(const sp<DeviceDescriptor> &device)
{ {
if (audio_is_output_device(availableDevice->type())) { if (audio_is_output_device(device->type())) {
mAvailableOutputDevices.add(availableDevice); mOutputDevices.add(device);
} else if (audio_is_input_device(availableDevice->type())) { } else if (audio_is_input_device(device->type())) {
mAvailableInputDevices.add(availableDevice); 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; } bool isSpeakerDrcEnabled() const { return mIsSpeakerDrcEnabled; }
@ -106,14 +106,14 @@ public:
const HwModuleCollection getHwModules() const { return mHwModules; } 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) void setDefaultOutputDevice(const sp<DeviceDescriptor> &defaultDevice)
@ -134,13 +134,11 @@ public:
sp<AudioProfile> micProfile = new AudioProfile( sp<AudioProfile> micProfile = new AudioProfile(
AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_MONO, 8000); AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_MONO, 8000);
defaultInputDevice->addAudioProfile(micProfile); defaultInputDevice->addAudioProfile(micProfile);
mAvailableOutputDevices.add(mDefaultOutputDevice); mOutputDevices.add(mDefaultOutputDevice);
mAvailableInputDevices.add(defaultInputDevice); mInputDevices.add(defaultInputDevice);
sp<HwModule> module = new HwModule(AUDIO_HARDWARE_MODULE_ID_PRIMARY, 2 /*halVersionMajor*/); sp<HwModule> module = new HwModule(AUDIO_HARDWARE_MODULE_ID_PRIMARY, 2 /*halVersionMajor*/);
mHwModules.add(module); mHwModules.add(module);
mDefaultOutputDevice->attach(module);
defaultInputDevice->attach(module);
sp<OutputProfile> outProfile = new OutputProfile("primary"); sp<OutputProfile> outProfile = new OutputProfile("primary");
outProfile->addAudioProfile( outProfile->addAudioProfile(
@ -191,8 +189,8 @@ private:
std::string mSource; std::string mSource;
std::string mEngineLibraryNameSuffix; std::string mEngineLibraryNameSuffix;
HwModuleCollection &mHwModules; /**< Collection of Module, with Profiles, i.e. Mix Ports. */ HwModuleCollection &mHwModules; /**< Collection of Module, with Profiles, i.e. Mix Ports. */
DeviceVector &mAvailableOutputDevices; DeviceVector &mOutputDevices;
DeviceVector &mAvailableInputDevices; DeviceVector &mInputDevices;
sp<DeviceDescriptor> &mDefaultOutputDevice; sp<DeviceDescriptor> &mDefaultOutputDevice;
// TODO: remove when legacy conf file is removed. true on devices that use DRC on the // 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. // 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(). sp<DeviceDescriptor> device = module->getDeclaredDevices().
getDeviceFromTagName(std::string(reinterpret_cast<const char*>( getDeviceFromTagName(std::string(reinterpret_cast<const char*>(
attachedDevice.get()))); attachedDevice.get())));
ctx->addAvailableDevice(device); ctx->addDevice(device);
} }
} }
} }

@ -4397,7 +4397,7 @@ AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterfa
mpClientInterface(clientInterface), mpClientInterface(clientInterface),
mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f), mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
mA2dpSuspended(false), mA2dpSuspended(false),
mConfig(mHwModulesAll, mAvailableOutputDevices, mAvailableInputDevices, mDefaultOutputDevice), mConfig(mHwModulesAll, mOutputDevicesAll, mInputDevicesAll, mDefaultOutputDevice),
mAudioPortGeneration(1), mAudioPortGeneration(1),
mBeaconMuteRefCount(0), mBeaconMuteRefCount(0),
mBeaconPlayingRefCount(0), mBeaconPlayingRefCount(0),
@ -4442,9 +4442,69 @@ status_t AudioPolicyManager::initialize() {
return status; 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 // 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) { for (const auto& hwModule : mHwModulesAll) {
if (std::find(mHwModules.begin(), mHwModules.end(), hwModule) != mHwModules.end()) {
continue;
}
hwModule->setHandle(mpClientInterface->loadHwModule(hwModule->getName())); hwModule->setHandle(mpClientInterface->loadHwModule(hwModule->getName()));
if (hwModule->getHandle() == AUDIO_MODULE_HANDLE_NONE) { if (hwModule->getHandle() == AUDIO_MODULE_HANDLE_NONE) {
ALOGW("could not open HW module %s", hwModule->getName()); ALOGW("could not open HW module %s", hwModule->getName());
@ -4473,7 +4533,7 @@ status_t AudioPolicyManager::initialize() {
continue; continue;
} }
const DeviceVector &supportedDevices = outProfile->getSupportedDevices(); const DeviceVector &supportedDevices = outProfile->getSupportedDevices();
DeviceVector availProfileDevices = supportedDevices.filter(mAvailableOutputDevices); DeviceVector availProfileDevices = supportedDevices.filter(mOutputDevicesAll);
sp<DeviceDescriptor> supportedDevice = 0; sp<DeviceDescriptor> supportedDevice = 0;
if (supportedDevices.contains(mDefaultOutputDevice)) { if (supportedDevices.contains(mDefaultOutputDevice)) {
supportedDevice = mDefaultOutputDevice; supportedDevice = mDefaultOutputDevice;
@ -4485,7 +4545,7 @@ status_t AudioPolicyManager::initialize() {
} }
supportedDevice = availProfileDevices.itemAt(0); supportedDevice = availProfileDevices.itemAt(0);
} }
if (!mAvailableOutputDevices.contains(supportedDevice)) { if (!mOutputDevicesAll.contains(supportedDevice)) {
continue; continue;
} }
sp<SwAudioOutputDescriptor> outputDesc = new SwAudioOutputDescriptor(outProfile, 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 // give a valid ID to an attached device once confirmed it is reachable
if (!device->isAttached()) { if (!device->isAttached()) {
device->attach(hwModule); device->attach(hwModule);
mAvailableOutputDevices.add(device);
setEngineDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
} }
} }
if (mPrimaryOutput == 0 && if (mPrimaryOutput == 0 &&
@ -4531,7 +4593,7 @@ status_t AudioPolicyManager::initialize() {
// chose first device present in profile's SupportedDevices also part of // chose first device present in profile's SupportedDevices also part of
// available input devices // available input devices
const DeviceVector &supportedDevices = inProfile->getSupportedDevices(); const DeviceVector &supportedDevices = inProfile->getSupportedDevices();
DeviceVector availProfileDevices = supportedDevices.filter(mAvailableInputDevices); DeviceVector availProfileDevices = supportedDevices.filter(mInputDevicesAll);
if (availProfileDevices.isEmpty()) { if (availProfileDevices.isEmpty()) {
ALOGE("%s: Input device list is empty!", __FUNCTION__); ALOGE("%s: Input device list is empty!", __FUNCTION__);
continue; continue;
@ -4556,81 +4618,15 @@ status_t AudioPolicyManager::initialize() {
if (!device->isAttached()) { if (!device->isAttached()) {
device->attach(hwModule); device->attach(hwModule);
device->importAudioPortAndPickAudioProfile(inProfile, true); device->importAudioPortAndPickAudioProfile(inProfile, true);
mAvailableInputDevices.add(device);
setEngineDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
} }
} }
inputDesc->close(); 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, void AudioPolicyManager::addOutput(audio_io_handle_t output,
const sp<SwAudioOutputDescriptor>& outputDesc) const sp<SwAudioOutputDescriptor>& outputDesc)
{ {

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

@ -1321,6 +1321,16 @@ bool AudioPolicyService::AudioCommandThread::threadLoop()
mLock.lock(); mLock.lock();
} }
} break; } 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: default:
ALOGW("AudioCommandThread() unknown command %d", command->mCommand); ALOGW("AudioCommandThread() unknown command %d", command->mCommand);
@ -1610,6 +1620,13 @@ void AudioPolicyService::AudioCommandThread::recordingConfigurationUpdateCommand
sendCommand(command); 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) status_t AudioPolicyService::AudioCommandThread::sendCommand(sp<AudioCommand>& command, int delayMs)
{ {
{ {
@ -1857,6 +1874,11 @@ void AudioPolicyService::setEffectSuspended(int effectId,
mAudioCommandThread->setEffectSuspendedCommand(effectId, sessionId, suspended); mAudioCommandThread->setEffectSuspendedCommand(effectId, sessionId, suspended);
} }
void AudioPolicyService::onNewAudioModulesAvailable()
{
mAudioCommandThread->audioModulesUpdateCommand();
}
extern "C" { extern "C" {
audio_module_handle_t aps_load_hw_module(void *service __unused, audio_module_handle_t aps_load_hw_module(void *service __unused,

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

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

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

@ -67,10 +67,10 @@ TEST(AudioHealthTest, AttachedDeviceFound) {
manager.loadConfig(); manager.loadConfig();
ASSERT_NE("AudioPolicyConfig::setDefault", manager.getConfig().getSource()); 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())); 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())); 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; audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE;
uid_t uid = 42; uid_t uid = 42;
const PatchCountCheck patchCount = snapshotPatchCount(); const PatchCountCheck patchCount = snapshotPatchCount();
ASSERT_FALSE(mManager->getConfig().getAvailableInputDevices().isEmpty()); ASSERT_FALSE(mManager->getAvailableInputDevices().isEmpty());
PatchBuilder patchBuilder; PatchBuilder patchBuilder;
patchBuilder.addSource(mManager->getConfig().getAvailableInputDevices()[0]). patchBuilder.addSource(mManager->getAvailableInputDevices()[0]).
addSink(mManager->getConfig().getDefaultOutputDevice()); addSink(mManager->getConfig().getDefaultOutputDevice());
ASSERT_EQ(NO_ERROR, mManager->createAudioPatch(patchBuilder.patch(), &handle, uid)); ASSERT_EQ(NO_ERROR, mManager->createAudioPatch(patchBuilder.patch(), &handle, uid));
ASSERT_NE(AUDIO_PATCH_HANDLE_NONE, handle); ASSERT_NE(AUDIO_PATCH_HANDLE_NONE, handle);
@ -334,15 +334,13 @@ void AudioPolicyManagerTestMsd::SetUpManagerConfig() {
sp<AudioProfile> pcmInputProfile = new AudioProfile( sp<AudioProfile> pcmInputProfile = new AudioProfile(
AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO, 44100); AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO, 44100);
mMsdInputDevice->addAudioProfile(pcmInputProfile); mMsdInputDevice->addAudioProfile(pcmInputProfile);
config.addAvailableDevice(mMsdOutputDevice); config.addDevice(mMsdOutputDevice);
config.addAvailableDevice(mMsdInputDevice); config.addDevice(mMsdInputDevice);
sp<HwModule> msdModule = new HwModule(AUDIO_HARDWARE_MODULE_ID_MSD, 2 /*halVersionMajor*/); sp<HwModule> msdModule = new HwModule(AUDIO_HARDWARE_MODULE_ID_MSD, 2 /*halVersionMajor*/);
HwModuleCollection modules = config.getHwModules(); HwModuleCollection modules = config.getHwModules();
modules.add(msdModule); modules.add(msdModule);
config.setHwModules(modules); config.setHwModules(modules);
mMsdOutputDevice->attach(msdModule);
mMsdInputDevice->attach(msdModule);
sp<OutputProfile> msdOutputProfile = new OutputProfile("msd input"); sp<OutputProfile> msdOutputProfile = new OutputProfile("msd input");
msdOutputProfile->addAudioProfile(pcmOutputProfile); msdOutputProfile->addAudioProfile(pcmOutputProfile);
@ -1127,3 +1125,40 @@ TEST_F(AudioPolicyManagerTVTest, MatchOutputDirectMMapNoIrq) {
AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_MMAP_NOIRQ), AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_MMAP_NOIRQ),
"low latency"); "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