Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c0d04987 authored by Mikhail Naganov's avatar Mikhail Naganov
Browse files

Allow for late audio module discovery in APM

Extract code that loads hardware modules and fills out
mAvailable{Input|Output}Devices into a reusable function.
It is used both during APM initialization and on
receiving a notification that a new HAL service has
been discovered.

Bug: 149854039
Test: atest audiopolicy_tests
Change-Id: Ifb7f0b61b06a0609802e63dccb26f3472328ef48
parent c62ad13a
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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,
+21 −23
Original line number Diff line number Diff line
@@ -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.
+1 −1
Original line number Diff line number Diff line
@@ -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);
                    }
                }
            }
+69 −73
Original line number Diff line number Diff line
@@ -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);
                }
            }
            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
                    mAvailableInputDevices.add(device);
                    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();
            inputDesc->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)
{
+6 −3
Original line number Diff line number Diff line
@@ -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;

Loading