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

Commit 28f14bd6 authored by Shunkai Yao's avatar Shunkai Yao
Browse files

Select first output supporting haptic if orphan haptic effect exist

Bug: 331687139
Test: atest CtsMediaAudioTestCases
Test: Hatptic test app on Pixel
Change-Id: Idcb2bb99f155555976baa0e6ed805ed0b8497baf
parent e8528998
Loading
Loading
Loading
Loading
+22 −7
Original line number Diff line number Diff line
@@ -32,11 +32,15 @@ class AudioPolicyClientInterface;
class EffectDescriptor : public RefBase
{
public:
    EffectDescriptor(const effect_descriptor_t *desc, bool isMusicEffect,
                     int id, audio_io_handle_t io, audio_session_t session) :
        mId(id), mIo(io), mSession(session), mEnabled(false), mSuspended(false),
        mIsMusicEffect(isMusicEffect)
    {
  EffectDescriptor(const effect_descriptor_t* desc, bool isMusicEffect, int id,
                   audio_io_handle_t io, audio_session_t session)
      : mId(id),
        mIo(io),
        mIsOrphan(io == AUDIO_IO_HANDLE_NONE),
        mSession(session),
        mEnabled(false),
        mSuspended(false),
        mIsMusicEffect(isMusicEffect) {
        memcpy (&mDesc, desc, sizeof(effect_descriptor_t));
    }

@@ -95,11 +99,22 @@ public:
     * @return ioHandle if found, AUDIO_IO_HANDLE_NONE otherwise.
     */
    audio_io_handle_t getIoForSession(audio_session_t sessionId,
                                      const effect_uuid_t *effectType = nullptr);
    bool hasOrphansForSession(audio_session_t sessionId);
                                      const effect_uuid_t *effectType = nullptr) const;
    bool hasOrphansForSession(audio_session_t sessionId) const;
    EffectDescriptorCollection getOrphanEffectsForSession(audio_session_t sessionId) const;
    void dump(String8 *dst, int spaces = 0, bool verbose = true) const;

    /**
     * @brief Checks if there is at least one orphan effect with given sessionId and effect type
     * uuid.
     * @param sessionId Session ID.
     * @param effectType Effect type UUID, the implementation will be same as hasOrphansForSession
     * if null.
     * @return True if there is an orphan effect for given sessionId and type UUID, false otherwise.
     */
    bool hasOrphanEffectsForSessionAndType(audio_session_t sessionId,
                                           const effect_uuid_t* effectType) const;

private:
    status_t setEffectEnabled(const sp<EffectDescriptor> &effectDesc, bool enabled);

+18 −2
Original line number Diff line number Diff line
@@ -210,7 +210,7 @@ void EffectDescriptorCollection::moveEffects(const std::vector<int>& ids, audio_
    }
}

bool EffectDescriptorCollection::hasOrphansForSession(audio_session_t sessionId)
bool EffectDescriptorCollection::hasOrphansForSession(audio_session_t sessionId) const
{
    for (size_t i = 0; i < size(); ++i) {
        sp<EffectDescriptor> effect = valueAt(i);
@@ -221,6 +221,22 @@ bool EffectDescriptorCollection::hasOrphansForSession(audio_session_t sessionId)
    return false;
}

bool EffectDescriptorCollection::hasOrphanEffectsForSessionAndType(
        audio_session_t sessionId, const effect_uuid_t* effectType) const {
    if (effectType == nullptr) {
        return hasOrphansForSession(sessionId);
    }

    for (size_t i = 0; i < size(); ++i) {
        sp<EffectDescriptor> effect = valueAt(i);
        if (effect->mIsOrphan && effect->mSession == sessionId &&
            memcmp(&effect->mDesc.type, effectType, sizeof(effect_uuid_t)) == 0) {
            return true;
        }
    }
    return false;
}

EffectDescriptorCollection EffectDescriptorCollection::getOrphanEffectsForSession(
        audio_session_t sessionId) const
{
@@ -235,7 +251,7 @@ EffectDescriptorCollection EffectDescriptorCollection::getOrphanEffectsForSessio
}

audio_io_handle_t EffectDescriptorCollection::getIoForSession(audio_session_t sessionId,
                                                              const effect_uuid_t *effectType)
                                                              const effect_uuid_t *effectType) const
{
    for (size_t i = 0; i < size(); ++i) {
        sp<EffectDescriptor> effect = valueAt(i);
+14 −5
Original line number Diff line number Diff line
@@ -2069,6 +2069,8 @@ audio_io_handle_t AudioPolicyManager::selectOutput(const SortedVector<audio_io_h
    // matching criteria values in priority order for best matching output so far
    std::vector<uint32_t> bestMatchCriteria(8, 0);

    const bool hasOrphanHaptic =
            mEffects.hasOrphanEffectsForSessionAndType(sessionId, FX_IID_HAPTICGENERATOR);
    const uint32_t channelCount = audio_channel_count_from_out_mask(channelMask);
    const uint32_t hapticChannelCount = audio_channel_count_from_out_mask(
        channelMask & AUDIO_CHANNEL_HAPTIC_ALL);
@@ -2089,12 +2091,19 @@ audio_io_handle_t AudioPolicyManager::selectOutput(const SortedVector<audio_io_h
        // When using haptic output, same audio format and sample rate are required.
        const uint32_t outputHapticChannelCount = audio_channel_count_from_out_mask(
            outputDesc->getChannelMask() & AUDIO_CHANNEL_HAPTIC_ALL);
        if ((hapticChannelCount == 0) != (outputHapticChannelCount == 0)) {
        // skip if haptic channel specified but output does not support it, or output support haptic
        // but there is no haptic channel requested AND no orphan haptic effect exist
        if ((hapticChannelCount != 0 && outputHapticChannelCount == 0) ||
            (hapticChannelCount == 0 && outputHapticChannelCount != 0 && !hasOrphanHaptic)) {
            continue;
        }
        if (outputHapticChannelCount >= hapticChannelCount
            && format == outputDesc->getFormat()
            && samplingRate == outputDesc->getSamplingRate()) {
        // In the case of audio-coupled-haptic playback, there is no format conversion and
        // resampling in the framework, same format/channel/sampleRate for client and the output
        // thread is required. In the case of HapticGenerator effect, do not require format
        // matching.
        if ((outputHapticChannelCount >= hapticChannelCount && format == outputDesc->getFormat() &&
             samplingRate == outputDesc->getSamplingRate()) ||
            (hapticChannelCount == 0 && hasOrphanHaptic)) {
            currentMatchCriteria[0] = outputHapticChannelCount;
        }