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

Commit ecc9f42b authored by Dorin Drimus's avatar Dorin Drimus
Browse files

Add MSD support for isDirectPlaybackSupported

isDirectOutputSupported will now also look into an MSD module if it
exists and check that audio patches are active to all desired output
devices.
Unit tests are included.

Bug: 196047314
Test: atest audiopolicy_tests
Change-Id: Iac23a441dee038b8e70c464d346063ea4162a9d8
parent 86508eb0
Loading
Loading
Loading
Loading
+94 −33
Original line number Diff line number Diff line
@@ -935,6 +935,32 @@ void AudioPolicyManager::setSystemProperty(const char* property, const char* val
    ALOGV("setSystemProperty() property %s, value %s", property, value);
}

// Find an MSD output profile compatible with the parameters passed.
// When "directOnly" is set, restrict search to profiles for direct outputs.
sp<IOProfile> AudioPolicyManager::getMsdProfileForOutput(
                                                   const DeviceVector& devices,
                                                   uint32_t samplingRate,
                                                   audio_format_t format,
                                                   audio_channel_mask_t channelMask,
                                                   audio_output_flags_t flags,
                                                   bool directOnly)
{
    flags = getRelevantFlags(flags, directOnly);

    sp<HwModule> msdModule = mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_MSD);
    if (msdModule != nullptr) {
        // for the msd module check if there are patches to the output devices
        if (msdHasPatchesToAllDevices(devices.toTypeAddrVector())) {
            HwModuleCollection modules;
            modules.add(msdModule);
            return searchCompatibleProfileHwModules(
                    modules, getMsdAudioOutDevices(), samplingRate, format, channelMask,
                    flags, directOnly);
        }
    }
    return nullptr;
}

// Find an output profile compatible with the parameters passed. When "directOnly" is set, restrict
// search to profiles for direct outputs.
sp<IOProfile> AudioPolicyManager::getProfileForOutput(
@@ -945,19 +971,35 @@ sp<IOProfile> AudioPolicyManager::getProfileForOutput(
                                                   audio_output_flags_t flags,
                                                   bool directOnly)
{
    flags = getRelevantFlags(flags, directOnly);

    return searchCompatibleProfileHwModules(
            mHwModules, devices, samplingRate, format, channelMask, flags, directOnly);
}

audio_output_flags_t AudioPolicyManager::getRelevantFlags (
                                            audio_output_flags_t flags, bool directOnly) {
    if (directOnly) {
         // only retain flags that will drive the direct output profile selection
         // if explicitly requested
         static const uint32_t kRelevantFlags =
                (AUDIO_OUTPUT_FLAG_HW_AV_SYNC | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD |
                AUDIO_OUTPUT_FLAG_VOIP_RX | AUDIO_OUTPUT_FLAG_MMAP_NOIRQ);
        flags =
            (audio_output_flags_t)((flags & kRelevantFlags) | AUDIO_OUTPUT_FLAG_DIRECT);
         flags = (audio_output_flags_t)((flags & kRelevantFlags) | AUDIO_OUTPUT_FLAG_DIRECT);
    }
    return flags;
}

sp<IOProfile> AudioPolicyManager::searchCompatibleProfileHwModules (
                                        const HwModuleCollection& hwModules,
                                        const DeviceVector& devices,
                                        uint32_t samplingRate,
                                        audio_format_t format,
                                        audio_channel_mask_t channelMask,
                                        audio_output_flags_t flags,
                                        bool directOnly) {
    sp<IOProfile> profile;

    for (const auto& hwModule : mHwModules) {
    for (const auto& hwModule : hwModules) {
        for (const auto& curProfile : hwModule->getOutputProfiles()) {
             if (!curProfile->isCompatibleProfile(devices,
                     samplingRate, NULL /*updatedSamplingRate*/,
@@ -974,10 +1016,14 @@ sp<IOProfile> AudioPolicyManager::getProfileForOutput(
             if (!curProfile->devicesSupportEncodedFormats(devices.types())) {
                 continue;
             }
            if (!directOnly) return curProfile;
             if (!directOnly) {
                return curProfile;
             }

             // when searching for direct outputs, if several profiles are compatible, give priority
             // to one with offload capability
            if (profile != 0 && ((curProfile->getFlags() & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0)) {
             if (profile != 0 && 
                 ((curProfile->getFlags() & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0)) {
                continue;
             }
             profile = curProfile;
@@ -3796,7 +3842,22 @@ bool AudioPolicyManager::isDirectOutputSupported(const audio_config_base_t& conf
        __FUNCTION__, profile != 0 ? "" : "NOT ",
        (profile != 0 ? profile->getTagName().c_str() : "null"),
        config.sample_rate, config.format, config.channel_mask, output_flags);
    return (profile != 0);

    // also try the MSD module if compatible profile not found
    if (profile == nullptr) {
        profile = getMsdProfileForOutput(outputDevices,
                                              config.sample_rate,
                                              config.format,
                                              config.channel_mask,
                                              output_flags,
                                              true /* directOnly */);
        ALOGV("%s() MSD profile %sfound with name: %s, "
            "sample rate: %u, format: 0x%x, channel_mask: 0x%x, output flags: 0x%x",
            __FUNCTION__, profile != 0 ? "" : "NOT ",
            (profile != 0 ? profile->getTagName().c_str() : "null"),
            config.sample_rate, config.format, config.channel_mask, output_flags);
    }
    return (profile != nullptr);
}

bool AudioPolicyManager::isOffloadPossible(const audio_offload_info_t &offloadInfo,
+24 −0
Original line number Diff line number Diff line
@@ -737,6 +737,15 @@ protected:
                                          audio_channel_mask_t channelMask,
                                          audio_output_flags_t flags,
                                          bool directOnly);
        /**
        * Same as getProfileForOutput, but it looks for an MSD profile
        */
        sp<IOProfile> getMsdProfileForOutput(const DeviceVector &devices,
                                           uint32_t samplingRate,
                                           audio_format_t format,
                                           audio_channel_mask_t channelMask,
                                           audio_output_flags_t flags,
                                           bool directOnly);

        audio_io_handle_t selectOutputForMusicEffects();

@@ -1155,6 +1164,21 @@ private:
        // without duplicating them if already present
        void addPortProfilesToVector(sp<IOProfile> outputProfile,
                                    AudioProfileVector& audioProfilesVector);

        // Searches for a compatible profile with the sample rate, audio format and channel mask
        // in the list of passed HwModule(s).
        // returns a compatible profile if found, nullptr otherwise
        sp<IOProfile> searchCompatibleProfileHwModules (
                                            const HwModuleCollection& hwModules,
                                            const DeviceVector& devices,
                                            uint32_t samplingRate,
                                            audio_format_t format,
                                            audio_channel_mask_t channelMask,
                                            audio_output_flags_t flags,
                                            bool directOnly);

        // Filters only the relevant flags for getProfileForOutput
        audio_output_flags_t getRelevantFlags (audio_output_flags_t flags, bool directOnly);
};

};
+67 −0
Original line number Diff line number Diff line
@@ -699,6 +699,73 @@ TEST_P(AudioPolicyManagerTestMsd, GetDirectProfilesForAttributesWithMsd) {
    ASSERT_EQ(countDirectProfilesPrimary, getDirectProfilesForAttributes(attr).size());
}

TEST_P(AudioPolicyManagerTestMsd, IsDirectPlaybackSupportedWithMsd) {
    const audio_attributes_t attr = {
        AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
        AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""};

    audio_config_base_t directConfig = AUDIO_CONFIG_BASE_INITIALIZER;
    directConfig.format = AUDIO_FORMAT_DTS;
    directConfig.sample_rate = 48000;
    directConfig.channel_mask = AUDIO_CHANNEL_OUT_5POINT1;

    audio_config_base_t nonDirectConfig = AUDIO_CONFIG_BASE_INITIALIZER;
    nonDirectConfig.format = AUDIO_FORMAT_PCM_16_BIT;
    nonDirectConfig.sample_rate = 48000;
    nonDirectConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;

    audio_config_base_t nonExistentConfig = AUDIO_CONFIG_BASE_INITIALIZER;
    nonExistentConfig.format = AUDIO_FORMAT_E_AC3;
    nonExistentConfig.sample_rate = 48000;
    nonExistentConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;

    audio_config_base_t msdDirectConfig1 = AUDIO_CONFIG_BASE_INITIALIZER;
    msdDirectConfig1.format = AUDIO_FORMAT_AC3;
    msdDirectConfig1.sample_rate = 48000;
    msdDirectConfig1.channel_mask = AUDIO_CHANNEL_OUT_5POINT1;

    audio_config_base_t msdDirectConfig2 = AUDIO_CONFIG_BASE_INITIALIZER;
    msdDirectConfig2.format = AUDIO_FORMAT_IEC60958;
    msdDirectConfig2.sample_rate = 48000;
    msdDirectConfig2.channel_mask = AUDIO_CHANNEL_OUT_STEREO;

    audio_config_base_t msdNonDirectConfig = AUDIO_CONFIG_BASE_INITIALIZER;
    msdNonDirectConfig.format = AUDIO_FORMAT_PCM_16_BIT;
    msdNonDirectConfig.sample_rate = 96000;
    msdNonDirectConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;

    ASSERT_TRUE(mManager->isDirectOutputSupported(directConfig, attr));
    ASSERT_FALSE(mManager->isDirectOutputSupported(nonDirectConfig, attr));
    ASSERT_FALSE(mManager->isDirectOutputSupported(nonExistentConfig, attr));
    // before setting MSD patches the direct MSD configs return false
    ASSERT_FALSE(mManager->isDirectOutputSupported(msdDirectConfig1, attr));
    ASSERT_FALSE(mManager->isDirectOutputSupported(msdDirectConfig2, attr));
    ASSERT_FALSE(mManager->isDirectOutputSupported(msdNonDirectConfig, attr));

    DeviceVector outputDevices = mManager->getAvailableOutputDevices();
    // Remove MSD output device to avoid patching to itself
    outputDevices.remove(mMsdOutputDevice);
    mManager->setMsdOutputPatches(&outputDevices);

    ASSERT_TRUE(mManager->isDirectOutputSupported(directConfig, attr));
    ASSERT_FALSE(mManager->isDirectOutputSupported(nonDirectConfig, attr));
    ASSERT_FALSE(mManager->isDirectOutputSupported(nonExistentConfig, attr));
    // after setting MSD patches the direct MSD configs return true
    ASSERT_TRUE(mManager->isDirectOutputSupported(msdDirectConfig1, attr));
    ASSERT_TRUE(mManager->isDirectOutputSupported(msdDirectConfig2, attr));
    ASSERT_FALSE(mManager->isDirectOutputSupported(msdNonDirectConfig, attr));

    mManager->releaseMsdOutputPatches(outputDevices);

    ASSERT_TRUE(mManager->isDirectOutputSupported(directConfig, attr));
    ASSERT_FALSE(mManager->isDirectOutputSupported(nonDirectConfig, attr));
    ASSERT_FALSE(mManager->isDirectOutputSupported(nonExistentConfig, attr));
    // AFTER releasing MSD patches the direct MSD configs return false
    ASSERT_FALSE(mManager->isDirectOutputSupported(msdDirectConfig1, attr));
    ASSERT_FALSE(mManager->isDirectOutputSupported(msdDirectConfig2, attr));
    ASSERT_FALSE(mManager->isDirectOutputSupported(msdNonDirectConfig, attr));
}

class AudioPolicyManagerTestWithConfigurationFile : public AudioPolicyManagerTest {
protected:
    void SetUpManagerConfig() override;