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

Commit 016cf79d authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "APM: return compatibility score to indicate how the profile is...

Merge "APM: return compatibility score to indicate how the profile is compatible for the given parameters." into main
parents f4a6c87c 66acc439
Loading
Loading
Loading
Loading
+20 −13
Original line number Diff line number Diff line
@@ -70,10 +70,17 @@ public:
        return mMixerBehaviors;
    }

    enum CompatibilityScore{
        NO_MATCH = 0,
        PARTIAL_MATCH = 1,
        EXACT_MATCH = 2
    };

    /**
     * @brief isCompatibleProfile: This method is used for input and direct output,
     * @brief compatibilityScore: This method is used for input and direct output,
     * and is not used for other output.
     * Checks if the IO profile is compatible with specified parameters.
     * Return the compatibility score to measure how much the IO profile is compatible
     * with specified parameters.
     * For input, flags is interpreted as audio_input_flags_t.
     * TODO: merge audio_output_flags_t and audio_input_flags_t.
     *
@@ -86,9 +93,9 @@ public:
     * @param updatedChannelMask if non-NULL, it is assigned the actual channel mask
     * @param flags to be checked for compatibility
     * @param exactMatchRequiredForInputFlags true if exact match is required on flags
     * @return true if the profile is compatible, false otherwise.
     * @return how the IO profile is compatible with the given parameters.
     */
    bool isCompatibleProfile(const DeviceVector &devices,
    CompatibilityScore getCompatibilityScore(const DeviceVector &devices,
                                             uint32_t samplingRate,
                                             uint32_t *updatedSamplingRate,
                                             audio_format_t format,
+31 −23
Original line number Diff line number Diff line
@@ -33,7 +33,8 @@ IOProfile::IOProfile(const std::string &name, audio_port_role_t role)
    }
}

bool IOProfile::isCompatibleProfile(const DeviceVector &devices,
IOProfile::CompatibilityScore IOProfile::getCompatibilityScore(
        const android::DeviceVector &devices,
        uint32_t samplingRate,
        uint32_t *updatedSamplingRate,
        audio_format_t format,
@@ -42,8 +43,7 @@ bool IOProfile::isCompatibleProfile(const DeviceVector &devices,
        audio_channel_mask_t *updatedChannelMask,
        // FIXME type punning here
        uint32_t flags,
                                    bool exactMatchRequiredForInputFlags) const
{
        bool exactMatchRequiredForInputFlags) const {
    const bool isPlaybackThread =
            getType() == AUDIO_PORT_TYPE_MIX && getRole() == AUDIO_PORT_ROLE_SOURCE;
    const bool isRecordThread =
@@ -51,13 +51,13 @@ bool IOProfile::isCompatibleProfile(const DeviceVector &devices,
    ALOG_ASSERT(isPlaybackThread != isRecordThread);
    if (!areAllDevicesSupported(devices) ||
            !isCompatibleProfileForFlags(flags, exactMatchRequiredForInputFlags)) {
        return false;
        return NO_MATCH;
    }

    if (!audio_is_valid_format(format) ||
            (isPlaybackThread && (samplingRate == 0 || !audio_is_output_channel(channelMask))) ||
            (isRecordThread && (!audio_is_input_channel(channelMask)))) {
         return false;
         return NO_MATCH;
    }

    audio_format_t myUpdatedFormat = format;
@@ -69,32 +69,40 @@ bool IOProfile::isCompatibleProfile(const DeviceVector &devices,
        .channel_mask = channelMask,
        .format = format,
    };
    auto result = NO_MATCH;
    if (isRecordThread)
    {
        if ((flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0) {
            if (checkExactAudioProfile(&config) != NO_ERROR) {
                return false;
            }
        } else if (checkExactAudioProfile(&config) != NO_ERROR && checkCompatibleAudioProfile(
                myUpdatedSamplingRate, myUpdatedChannelMask, myUpdatedFormat) != NO_ERROR) {
            return false;
                return result;
            }
            result = EXACT_MATCH;
        } else if (checkExactAudioProfile(&config) == NO_ERROR) {
            result = EXACT_MATCH;
        } else if (checkCompatibleAudioProfile(
                myUpdatedSamplingRate, myUpdatedChannelMask, myUpdatedFormat) == NO_ERROR) {
            result = PARTIAL_MATCH;
        } else {
            return result;
        }
    } else {
        if (checkExactAudioProfile(&config) != NO_ERROR) {
            return false;
        if (checkExactAudioProfile(&config) == NO_ERROR) {
            result = EXACT_MATCH;
        } else {
            return result;
        }
    }

    if (updatedSamplingRate != NULL) {
    if (updatedSamplingRate != nullptr) {
        *updatedSamplingRate = myUpdatedSamplingRate;
    }
    if (updatedFormat != NULL) {
    if (updatedFormat != nullptr) {
        *updatedFormat = myUpdatedFormat;
    }
    if (updatedChannelMask != NULL) {
    if (updatedChannelMask != nullptr) {
        *updatedChannelMask = myUpdatedChannelMask;
    }
    return true;
    return result;
}

bool IOProfile::areAllDevicesSupported(const DeviceVector &devices) const {
+63 −54
Original line number Diff line number Diff line
@@ -1050,11 +1050,11 @@ sp<IOProfile> AudioPolicyManager::searchCompatibleProfileHwModules (
    sp<IOProfile> profile;
    for (const auto& hwModule : hwModules) {
        for (const auto& curProfile : hwModule->getOutputProfiles()) {
             if (!curProfile->isCompatibleProfile(devices,
             if (curProfile->getCompatibilityScore(devices,
                     samplingRate, NULL /*updatedSamplingRate*/,
                     format, NULL /*updatedFormat*/,
                     channelMask, NULL /*updatedChannelMask*/,
                     flags)) {
                     flags) == IOProfile::NO_MATCH) {
                 continue;
             }
             // reject profiles not corresponding to a device currently available
@@ -4486,11 +4486,11 @@ audio_direct_mode_t AudioPolicyManager::getDirectPlaybackSupport(const audio_att
            outputDevices = getMsdAudioOutDevices();
        }
        for (const auto& curProfile : hwModule->getOutputProfiles()) {
            if (!curProfile->isCompatibleProfile(outputDevices,
            if (curProfile->getCompatibilityScore(outputDevices,
                    config->sample_rate, nullptr /*updatedSamplingRate*/,
                    config->format, nullptr /*updatedFormat*/,
                    config->channel_mask, nullptr /*updatedChannelMask*/,
                    flags)) {
                    flags) == IOProfile::NO_MATCH) {
                continue;
            }
            // reject profiles not corresponding to a device currently available
@@ -4596,7 +4596,8 @@ status_t AudioPolicyManager::setPreferredMixerAttributes(
    for (const auto& hwModule : mHwModules) {
        for (const auto& curProfile : hwModule->getOutputProfiles()) {
            if (curProfile->hasDynamicAudioProfile()
                    && curProfile->isCompatibleProfile(devices,
                    && curProfile->getCompatibilityScore(
                            devices,
                            mixerAttributes->config.sample_rate,
                            nullptr /*updatedSamplingRate*/,
                            mixerAttributes->config.format,
@@ -4604,7 +4605,8 @@ status_t AudioPolicyManager::setPreferredMixerAttributes(
                            mixerAttributes->config.channel_mask,
                            nullptr /*updatedChannelMask*/,
                            flags,
                                                       false /*exactMatchRequiredForInputFlags*/)) {
                            false /*exactMatchRequiredForInputFlags*/)
                            != IOProfile::NO_MATCH) {
                profile = curProfile;
                break;
            }
@@ -5009,14 +5011,15 @@ status_t AudioPolicyManager::createAudioPatchInternal(const struct audio_patch *
                return BAD_VALUE;
            }

            if (!outputDesc->mProfile->isCompatibleProfile(DeviceVector(devDesc),
            if (outputDesc->mProfile->getCompatibilityScore(
                    DeviceVector(devDesc),
                    patch->sources[0].sample_rate,
                                                           NULL,  // updatedSamplingRate
                    nullptr,  // updatedSamplingRate
                    patch->sources[0].format,
                                                           NULL,  // updatedFormat
                    nullptr,  // updatedFormat
                    patch->sources[0].channel_mask,
                                                           NULL,  // updatedChannelMask
                                                           AUDIO_OUTPUT_FLAG_NONE /*FIXME*/)) {
                    nullptr,  // updatedChannelMask
                    AUDIO_OUTPUT_FLAG_NONE /*FIXME*/) == IOProfile::NO_MATCH) {
                ALOGV("%s profile not supported for device %08x", __func__, devDesc->type());
                return INVALID_OPERATION;
            }
@@ -5064,17 +5067,18 @@ status_t AudioPolicyManager::createAudioPatchInternal(const struct audio_patch *
                return BAD_VALUE;
            }

            if (!inputDesc->mProfile->isCompatibleProfile(DeviceVector(device),
            if (inputDesc->mProfile->getCompatibilityScore(
                    DeviceVector(device),
                    patch->sinks[0].sample_rate,
                                                          NULL, /*updatedSampleRate*/
                    nullptr, /*updatedSampleRate*/
                    patch->sinks[0].format,
                                                          NULL, /*updatedFormat*/
                    nullptr, /*updatedFormat*/
                    patch->sinks[0].channel_mask,
                                                          NULL, /*updatedChannelMask*/
                    nullptr, /*updatedChannelMask*/
                    // FIXME for the parameter type,
                    // and the NONE
                    (audio_output_flags_t)
                                                            AUDIO_INPUT_FLAG_NONE)) {
                    AUDIO_INPUT_FLAG_NONE) == IOProfile::NO_MATCH) {
                return INVALID_OPERATION;
            }
            // TODO: reconfigure output format and channels here
@@ -7696,9 +7700,6 @@ sp<IOProfile> AudioPolicyManager::getInputProfile(const sp<DeviceDescriptor> &de
    // Choose an input profile based on the requested capture parameters: select the first available
    // profile supporting all requested parameters.
    // The flags can be ignored if it doesn't contain a much match flag.
    //
    // TODO: perhaps isCompatibleProfile should return a "matching" score so we can return
    // the best matching profile, not the first one.

    using underlying_input_flag_t = std::underlying_type_t<audio_input_flags_t>;
    const underlying_input_flag_t mustMatchFlag = AUDIO_INPUT_FLAG_MMAP_NOIRQ |
@@ -7715,18 +7716,25 @@ sp<IOProfile> AudioPolicyManager::getInputProfile(const sp<DeviceDescriptor> &de
            for (const auto& profile : hwModule->getInputProfiles()) {
                // profile->log();
                //updatedFormat = format;
                if (profile->isCompatibleProfile(DeviceVector(device), samplingRate,
                                                 &samplingRate  /*updatedSamplingRate*/,
                if (profile->getCompatibilityScore(
                        DeviceVector(device),
                        samplingRate,
                        &updatedSamplingRate,
                        format,
                                                 &format,       /*updatedFormat*/
                        &updatedFormat,
                        channelMask,
                                                 &channelMask   /*updatedChannelMask*/,
                        &updatedChannelMask,
                        // FIXME ugly cast
                        (audio_output_flags_t) flags,
                                                 true /*exactMatchRequiredForInputFlags*/)) {
                        true /*exactMatchRequiredForInputFlags*/) == IOProfile::EXACT_MATCH) {
                    samplingRate = updatedSamplingRate;
                    format = updatedFormat;
                    channelMask = updatedChannelMask;
                    return profile;
                }
                if (firstInexact == nullptr && profile->isCompatibleProfile(DeviceVector(device),
                if (firstInexact == nullptr
                        && profile->getCompatibilityScore(
                                DeviceVector(device),
                                samplingRate,
                                &updatedSamplingRate,
                                format,
@@ -7735,7 +7743,8 @@ sp<IOProfile> AudioPolicyManager::getInputProfile(const sp<DeviceDescriptor> &de
                                &updatedChannelMask,
                                // FIXME ugly cast
                                (audio_output_flags_t) flags,
                                                 false /*exactMatchRequiredForInputFlags*/)) {
                                false /*exactMatchRequiredForInputFlags*/)
                                != IOProfile::NO_MATCH) {
                    firstInexact = profile;
                }
            }
+1 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ class AudioPolicyTestManager : public AudioPolicyManager {
    using AudioPolicyManager::getConfig;
    using AudioPolicyManager::initialize;
    using AudioPolicyManager::getOutputs;
    using AudioPolicyManager::getInputs;
    using AudioPolicyManager::getAvailableOutputDevices;
    using AudioPolicyManager::getAvailableInputDevices;
    using AudioPolicyManager::setSurroundFormatEnabled;
+53 −0
Original line number Diff line number Diff line
@@ -92,6 +92,12 @@ AttributionSourceState createAttributionSourceState(uid_t uid) {
    return attributionSourceState;
}

bool equals(const audio_config_base_t& config1, const audio_config_base_t& config2) {
    return config1.format == config2.format
            && config1.sample_rate == config2.sample_rate
            && config1.channel_mask == config2.channel_mask;
}

} // namespace

TEST(AudioPolicyConfigTest, DefaultConfigForTestsIsEmpty) {
@@ -1266,6 +1272,53 @@ TEST_F(AudioPolicyManagerTestWithConfigurationFile, BitPerfectPlayback) {
                                                           "", "", AUDIO_FORMAT_LDAC));
}

TEST_F(AudioPolicyManagerTestWithConfigurationFile, PreferExactConfigForInput) {
    const audio_channel_mask_t deviceChannelMask = AUDIO_CHANNEL_IN_3POINT1;
    mClient->addSupportedFormat(AUDIO_FORMAT_PCM_16_BIT);
    mClient->addSupportedChannelMask(deviceChannelMask);
    ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(AUDIO_DEVICE_IN_USB_DEVICE,
                                                           AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
                                                           "", "", AUDIO_FORMAT_DEFAULT));

    audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
    audio_attributes_t attr = {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
                               AUDIO_SOURCE_VOICE_COMMUNICATION,AUDIO_FLAG_NONE, ""};
    AudioPolicyInterface::input_type_t inputType;
    audio_io_handle_t input = AUDIO_PORT_HANDLE_NONE;
    AttributionSourceState attributionSource = createAttributionSourceState(/*uid=*/ 0);
    audio_config_base_t requestedConfig = {
            .channel_mask = AUDIO_CHANNEL_IN_STEREO,
            .format = AUDIO_FORMAT_PCM_16_BIT,
            .sample_rate = 48000
    };
    audio_config_base_t config = requestedConfig;
    audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
    ASSERT_EQ(OK, mManager->getInputForAttr(
            &attr, &input, 1 /*riid*/, AUDIO_SESSION_NONE, attributionSource, &config,
            AUDIO_INPUT_FLAG_NONE,
            &selectedDeviceId, &inputType, &portId));
    ASSERT_NE(AUDIO_PORT_HANDLE_NONE, portId);
    ASSERT_TRUE(equals(requestedConfig, config));

    attr = {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
            AUDIO_SOURCE_VOICE_COMMUNICATION, AUDIO_FLAG_NONE, ""};
    requestedConfig.channel_mask = deviceChannelMask;
    config = requestedConfig;
    selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
    input = AUDIO_PORT_HANDLE_NONE;
    portId = AUDIO_PORT_HANDLE_NONE;
    ASSERT_EQ(OK, mManager->getInputForAttr(
            &attr, &input, 1 /*riid*/, AUDIO_SESSION_NONE, attributionSource, &config,
            AUDIO_INPUT_FLAG_NONE,
            &selectedDeviceId, &inputType, &portId));
    ASSERT_NE(AUDIO_PORT_HANDLE_NONE, portId);
    ASSERT_TRUE(equals(requestedConfig, config));

    ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(AUDIO_DEVICE_IN_USB_DEVICE,
                                                           AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
                                                           "", "", AUDIO_FORMAT_DEFAULT));
}

class AudioPolicyManagerTestDynamicPolicy : public AudioPolicyManagerTestWithConfigurationFile {
protected:
    void TearDown() override;
Loading