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

Commit dff2a4f7 authored by jiabin's avatar jiabin
Browse files

Make audio port in policy not derive from audio port base

This patch aims to make the structure for libaudiofoundation and policy
stuff simpler, including:
1. Make AudioPortBase as AudioPort in libaudiofoundation. Create
PolicyAudioPort that contains policy related stuff, which is used by
audiopolicy.
2. Make AudioPortConfigBase as AudioPortConfig in libaudiofoundation.
Create PolicyAudioPortConfig that contains policy related stuff.
3. DeviceDescriptor derives from AudioPort, AudioPortConfig, PolicyAudioPort
and PolicyAudioPortConfig. IOProfile derives from AudioPort,
PolicyAudioPort. AudioInputDescriptor/AudioOutputDescriptor derives from
AudioPortConfig, PolicyAudioPortConfig.

Test: atest AudioTrackTest, AudioRecordTest, AudioManagerTest
Test: atest audiopolicy_tests, AudioHostTest
Test: audio smoke test
Bug: 135621476
Change-Id: I40299d95dda3b3fc0ea88b079f2fe38d8f7e5b31
Merged-In: I40299d95dda3b3fc0ea88b079f2fe38d8f7e5b31
parent c0254615
Loading
Loading
Loading
Loading
+106 −2
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#define LOG_TAG "AudioPortBase"

#include <algorithm>

@@ -22,7 +23,22 @@

namespace android {

void AudioPortBase::toAudioPort(struct audio_port *port) const {
void AudioPort::importAudioPort(const sp<AudioPort>& port, bool force __unused)
{
    for (const auto& profileToImport : port->mProfiles) {
        // Import only valid port, i.e. valid format, non empty rates and channels masks
        if (!profileToImport->isValid()) {
            continue;
        }
        if (std::find_if(mProfiles.begin(), mProfiles.end(),
                [profileToImport](const auto &profile) {
                        return *profile == *profileToImport; }) == mProfiles.end()) {
            addAudioProfile(profileToImport);
        }
    }
}

void AudioPort::toAudioPort(struct audio_port *port) const {
    // TODO: update this function once audio_port structure reflects the new profile definition.
    // For compatibility reason: flatening the AudioProfile into audio_port structure.
    FormatSet flatenedFormats;
@@ -64,7 +80,7 @@ void AudioPortBase::toAudioPort(struct audio_port *port) const {
    }
}

void AudioPortBase::dump(std::string *dst, int spaces, bool verbose) const {
void AudioPort::dump(std::string *dst, int spaces, bool verbose) const {
    if (!mName.empty()) {
        dst->append(base::StringPrintf("%*s- name: %s\n", spaces, "", mName.c_str()));
    }
@@ -84,4 +100,92 @@ void AudioPortBase::dump(std::string *dst, int spaces, bool verbose) const {
    }
}

void AudioPort::log(const char* indent) const
{
    ALOGI("%s Port[nm:%s, type:%d, role:%d]", indent, mName.c_str(), mType, mRole);
}

// --- AudioPortConfig class implementation

status_t AudioPortConfig::applyAudioPortConfig(
        const struct audio_port_config *config,
        struct audio_port_config *backupConfig __unused)
{
    if (config->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
        mSamplingRate = config->sample_rate;
    }
    if (config->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
        mChannelMask = config->channel_mask;
    }
    if (config->config_mask & AUDIO_PORT_CONFIG_FORMAT) {
        mFormat = config->format;
    }
    if (config->config_mask & AUDIO_PORT_CONFIG_GAIN) {
        mGain = config->gain;
    }

    return NO_ERROR;
}

namespace {

template<typename T>
void updateField(
        const T& portConfigField, T audio_port_config::*port_config_field,
        struct audio_port_config *dstConfig, const struct audio_port_config *srcConfig,
        unsigned int configMask, T defaultValue)
{
    if (dstConfig->config_mask & configMask) {
        if ((srcConfig != nullptr) && (srcConfig->config_mask & configMask)) {
            dstConfig->*port_config_field = srcConfig->*port_config_field;
        } else {
            dstConfig->*port_config_field = portConfigField;
        }
    } else {
        dstConfig->*port_config_field = defaultValue;
    }
}

} // namespace

void AudioPortConfig::toAudioPortConfig(
        struct audio_port_config *dstConfig,
        const struct audio_port_config *srcConfig) const
{
    updateField(mSamplingRate, &audio_port_config::sample_rate,
            dstConfig, srcConfig, AUDIO_PORT_CONFIG_SAMPLE_RATE, 0u);
    updateField(mChannelMask, &audio_port_config::channel_mask,
            dstConfig, srcConfig, AUDIO_PORT_CONFIG_CHANNEL_MASK,
            (audio_channel_mask_t)AUDIO_CHANNEL_NONE);
    updateField(mFormat, &audio_port_config::format,
            dstConfig, srcConfig, AUDIO_PORT_CONFIG_FORMAT, AUDIO_FORMAT_INVALID);
    dstConfig->id = mId;

    sp<AudioPort> audioport = getAudioPort();
    if ((dstConfig->config_mask & AUDIO_PORT_CONFIG_GAIN) && audioport != NULL) {
        dstConfig->gain = mGain;
        if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_GAIN)
                && audioport->checkGain(&srcConfig->gain, srcConfig->gain.index) == OK) {
            dstConfig->gain = srcConfig->gain;
        }
    } else {
        dstConfig->gain.index = -1;
    }
    if (dstConfig->gain.index != -1) {
        dstConfig->config_mask |= AUDIO_PORT_CONFIG_GAIN;
    } else {
        dstConfig->config_mask &= ~AUDIO_PORT_CONFIG_GAIN;
    }
}

bool AudioPortConfig::hasGainController(bool canUseForVolume) const
{
    sp<AudioPort> audioport = getAudioPort();
    if (!audioport) {
        return false;
    }
    return canUseForVolume ? audioport->getGains().canUseForVolume()
                           : audioport->getGains().size() > 0;
}

}
 No newline at end of file
+20 −9
Original line number Diff line number Diff line
@@ -27,13 +27,13 @@

namespace android {

class AudioPortBase : public virtual RefBase
class AudioPort : public virtual RefBase
{
public:
    AudioPortBase(const std::string& name, audio_port_type_t type,  audio_port_role_t role) :
    AudioPort(const std::string& name, audio_port_type_t type,  audio_port_role_t role) :
            mName(name), mType(type), mRole(role) {}

    virtual ~AudioPortBase() = default;
    virtual ~AudioPort() = default;

    void setName(const std::string &name) { mName = name; }
    const std::string &getName() const { return mName; }
@@ -41,8 +41,6 @@ public:
    audio_port_type_t getType() const { return mType; }
    audio_port_role_t getRole() const { return mRole; }

    virtual const std::string getTagName() const = 0;

    void setGains(const AudioGains &gains) { mGains = gains; }
    const AudioGains &getGains() const { return mGains; }

@@ -57,9 +55,13 @@ public:

    bool hasValidAudioProfile() const { return mProfiles.hasValidProfile(); }

    bool hasDynamicAudioProfile() const { return mProfiles.hasDynamicProfile(); }

    void setAudioProfiles(const AudioProfileVector &profiles) { mProfiles = profiles; }
    AudioProfileVector &getAudioProfiles() { return mProfiles; }

    virtual void importAudioPort(const sp<AudioPort>& port, bool force = false);

    status_t checkGain(const struct audio_gain_config *gainConfig, int index) const {
        if (index < 0 || (size_t)index >= mGains.size()) {
            return BAD_VALUE;
@@ -75,6 +77,8 @@ public:

    void dump(std::string *dst, int spaces, bool verbose = true) const;

    void log(const char* indent) const;

    AudioGains mGains; // gain controllers
protected:
    std::string  mName;
@@ -84,24 +88,31 @@ protected:
};


class AudioPortConfigBase : public virtual RefBase
class AudioPortConfig : public virtual RefBase
{
public:
    virtual ~AudioPortConfigBase() = default;
    virtual ~AudioPortConfig() = default;

    virtual sp<AudioPort> getAudioPort() const = 0;

    virtual status_t applyAudioPortConfig(const struct audio_port_config *config,
                                          struct audio_port_config *backupConfig = NULL) = 0;
                                          struct audio_port_config *backupConfig = NULL);

    virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
                                   const struct audio_port_config *srcConfig = NULL) const = 0;
                                   const struct audio_port_config *srcConfig = NULL) const;

    unsigned int getSamplingRate() const { return mSamplingRate; }
    audio_format_t getFormat() const { return mFormat; }
    audio_channel_mask_t getChannelMask() const { return mChannelMask; }
    audio_port_handle_t getId() const { return mId; }

    bool hasGainController(bool canUseForVolume = false) const;

protected:
    unsigned int mSamplingRate = 0u;
    audio_format_t mFormat = AUDIO_FORMAT_INVALID;
    audio_channel_mask_t mChannelMask = AUDIO_CHANNEL_NONE;
    audio_port_handle_t mId = AUDIO_PORT_HANDLE_NONE;
    struct audio_gain_config mGain = { .index = -1 };
};

+6 −11
Original line number Diff line number Diff line
@@ -25,20 +25,15 @@

namespace android {

class AudioPort;
class PolicyAudioPort;
class AudioRoute;

class AudioPortVector : public Vector<sp<AudioPort> >
{
public:
    sp<AudioPort> findByTagName(const std::string &tagName) const;
};
using PolicyAudioPortVector = Vector<sp<PolicyAudioPort>>;
using AudioRouteVector = Vector<sp<AudioRoute>>;

sp<PolicyAudioPort> findByTagName(const PolicyAudioPortVector& policyAudioPortVector,
                                  const std::string &tagName);

class AudioRouteVector : public Vector<sp<AudioRoute> >
{
public:
    void dump(String8 *dst, int spaces) const;
};
void dumpAudioRouteVector(const AudioRouteVector& audioRouteVector, String8 *dst, int spaces);

} // namespace android
+18 −6
Original line number Diff line number Diff line
@@ -34,13 +34,17 @@ class AudioPolicyClientInterface;

// descriptor for audio inputs. Used to maintain current configuration of each opened audio input
// and keep track of the usage of this input.
class AudioInputDescriptor: public AudioPortConfig, public AudioIODescriptorInterface
    , public ClientMapHandler<RecordClientDescriptor>
class AudioInputDescriptor: public AudioPortConfig,
        public PolicyAudioPortConfig,
        public AudioIODescriptorInterface,
        public ClientMapHandler<RecordClientDescriptor>
{
public:
    explicit AudioInputDescriptor(const sp<IOProfile>& profile,
    AudioInputDescriptor(const sp<IOProfile>& profile,
                         AudioPolicyClientInterface *clientInterface);
    audio_port_handle_t getId() const;

    virtual ~AudioInputDescriptor() = default;

    audio_module_handle_t getModuleHandle() const;

    audio_devices_t getDeviceType() const { return (mDevice != nullptr) ?
@@ -56,9 +60,18 @@ public:
    wp<AudioPolicyMix>  mPolicyMix;                   // non NULL when used by a dynamic policy
    const sp<IOProfile> mProfile;                     // I/O profile this output derives from

    // PolicyAudioPortConfig
    virtual sp<PolicyAudioPort> getPolicyAudioPort() const {
        return mProfile;
    }

    // AudioPortConfig
    virtual status_t applyAudioPortConfig(const struct audio_port_config *config,
                                          struct audio_port_config *backupConfig = NULL);
    virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
            const struct audio_port_config *srcConfig = NULL) const;
    virtual sp<AudioPort> getAudioPort() const { return mProfile; }

    void toAudioPort(struct audio_port *port) const;
    void setPreemptedSessions(const SortedVector<audio_session_t>& sessions);
    SortedVector<audio_session_t> getPreemptedSessions() const;
@@ -111,7 +124,6 @@ public:
    void updateClientRecordingConfiguration(int event, const sp<RecordClientDescriptor>& client);

    audio_patch_handle_t mPatchHandle = AUDIO_PATCH_HANDLE_NONE;
    audio_port_handle_t  mId = AUDIO_PORT_HANDLE_NONE;
    sp<DeviceDescriptor> mDevice = nullptr; /**< current device this input is routed to */

    // Because a preemptible capture session can preempt another one, we end up in an endless loop
+17 −7
Original line number Diff line number Diff line
@@ -138,18 +138,19 @@ using RoutingActivities = std::map<product_strategy_t, RoutingActivity>;

// descriptor for audio outputs. Used to maintain current configuration of each opened audio output
// and keep track of the usage of this output by each audio stream type.
class AudioOutputDescriptor: public AudioPortConfig, public AudioIODescriptorInterface
    , public ClientMapHandler<TrackClientDescriptor>
class AudioOutputDescriptor: public AudioPortConfig,
        public PolicyAudioPortConfig,
        public AudioIODescriptorInterface,
        public ClientMapHandler<TrackClientDescriptor>
{
public:
    AudioOutputDescriptor(const sp<AudioPort>& port,
    AudioOutputDescriptor(const sp<PolicyAudioPort>& policyAudioPort,
                          AudioPolicyClientInterface *clientInterface);
    virtual ~AudioOutputDescriptor() {}

    void dump(String8 *dst) const override;
    void        log(const char* indent);

    audio_port_handle_t getId() const;
    virtual DeviceVector devices() const { return mDevices; }
    bool sharesHwModuleWith(const sp<AudioOutputDescriptor>& outputDesc);
    virtual DeviceVector supportedDevices() const  { return mDevices; }
@@ -245,9 +246,19 @@ public:
        mRoutingActivities[ps].setMutedByDevice(isMuted);
    }

    // PolicyAudioPortConfig
    virtual sp<PolicyAudioPort> getPolicyAudioPort() const
    {
        return mPolicyAudioPort;
    }

    // AudioPortConfig
    virtual status_t applyAudioPortConfig(const struct audio_port_config *config,
                                          struct audio_port_config *backupConfig = NULL);
    virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
                           const struct audio_port_config *srcConfig = NULL) const;
    virtual sp<AudioPort> getAudioPort() const { return mPort; }
    virtual sp<AudioPort> getAudioPort() const { return mPolicyAudioPort->asAudioPort(); }

    virtual void toAudioPort(struct audio_port *port) const;

    audio_module_handle_t getModuleHandle() const;
@@ -289,11 +300,10 @@ public:
    wp<AudioPolicyMix> mPolicyMix;  // non NULL when used by a dynamic policy

protected:
    const sp<AudioPort> mPort;
    const sp<PolicyAudioPort> mPolicyAudioPort;
    AudioPolicyClientInterface * const mClientInterface;
    uint32_t mGlobalActiveCount = 0;  // non-client-specific active count
    audio_patch_handle_t mPatchHandle = AUDIO_PATCH_HANDLE_NONE;
    audio_port_handle_t mId = AUDIO_PORT_HANDLE_NONE;

    // The ActiveClients shows the clients that contribute to the @VolumeSource counts
    // and may include upstream clients from a duplicating thread.
Loading