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

Commit 7ef477e1 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge changes I2a915950,I968b705c into main

* changes:
  Close input streams for external devices immediately after probing
  APM: return compatibility score to indicate how the profile is compatible for the given parameters.
parents 71809ba8 2b61ab56
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 {
+95 −79
Original line number Diff line number Diff line
@@ -390,8 +390,12 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(const sp<DeviceDescript
            // Before checking intputs, broadcast connect event to allow HAL to retrieve dynamic
            // parameters on newly connected devices (instead of opening the inputs...)
            broadcastDeviceConnectionState(device, media::DeviceConnectedState::CONNECTED);
            // Propagate device availability to Engine
            setEngineDeviceConnectionState(device, state);

            if (checkInputsForDevice(device, state) != NO_ERROR) {
                setEngineDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE);

                mAvailableInputDevices.remove(device);

                broadcastDeviceConnectionState(device, media::DeviceConnectedState::DISCONNECTED);
@@ -425,6 +429,9 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(const sp<DeviceDescript

            // remove device from mReportedFormatsMap cache
            mReportedFormatsMap.erase(device);

            // Propagate device availability to Engine
            setEngineDeviceConnectionState(device, state);
        } break;

        default:
@@ -432,9 +439,6 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(const sp<DeviceDescript
            return BAD_VALUE;
        }

        // Propagate device availability to Engine
        setEngineDeviceConnectionState(device, state);

        checkCloseInputs();
        // As the input device list can impact the output device selection, update
        // getDeviceForStrategy() cache
@@ -1043,11 +1047,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
@@ -3175,37 +3179,35 @@ void AudioPolicyManager::closeClient(audio_port_handle_t portId)
    releaseInput(portId);
}

void AudioPolicyManager::checkCloseInputs() {
    // After connecting or disconnecting an input device, close input if:
    // - it has no client (was just opened to check profile)  OR
    // - none of its supported devices are connected anymore OR
    // - one of its clients cannot be routed to one of its supported
    // devices anymore. Otherwise update device selection
    std::vector<audio_io_handle_t> inputsToClose;
    for (size_t i = 0; i < mInputs.size(); i++) {
        const sp<AudioInputDescriptor> input = mInputs.valueAt(i);
bool AudioPolicyManager::checkCloseInput(const sp<AudioInputDescriptor>& input) {
    if (input->clientsList().size() == 0
            || !mAvailableInputDevices.containsAtLeastOne(input->supportedDevices())) {
            inputsToClose.push_back(mInputs.keyAt(i));
        } else {
            bool close = false;
        return true;
    }
    for (const auto& client : input->clientsList()) {
        sp<DeviceDescriptor> device =
            mEngine->getInputDeviceForAttributes(client->attributes(), client->uid(),
                                                 client->session());
        if (!input->supportedDevices().contains(device)) {
                    close = true;
                    break;
            return true;
        }
    }
            if (close) {
                inputsToClose.push_back(mInputs.keyAt(i));
            } else {
    setInputDevice(input->mIoHandle, getNewInputDevice(input));
    return false;
}

void AudioPolicyManager::checkCloseInputs() {
    // After connecting or disconnecting an input device, close input if:
    // - it has no client (was just opened to check profile)  OR
    // - none of its supported devices are connected anymore OR
    // - one of its clients cannot be routed to one of its supported
    // devices anymore. Otherwise update device selection
    std::vector<audio_io_handle_t> inputsToClose;
    for (size_t i = 0; i < mInputs.size(); i++) {
        if (checkCloseInput(mInputs.valueAt(i))) {
            inputsToClose.push_back(mInputs.keyAt(i));
        }
    }

    for (const audio_io_handle_t handle : inputsToClose) {
        ALOGV("%s closing input %d", __func__, handle);
        closeInput(handle);
@@ -4463,11 +4465,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
@@ -4573,7 +4575,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,
@@ -4581,7 +4584,8 @@ status_t AudioPolicyManager::setPreferredMixerAttributes(
                            mixerAttributes->config.channel_mask,
                            nullptr /*updatedChannelMask*/,
                            flags,
                                                       false /*exactMatchRequiredForInputFlags*/)) {
                            false /*exactMatchRequiredForInputFlags*/)
                            != IOProfile::NO_MATCH) {
                profile = curProfile;
                break;
            }
@@ -4984,14 +4988,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;
            }
@@ -5039,17 +5044,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
@@ -6606,14 +6612,14 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor>& d
status_t AudioPolicyManager::checkInputsForDevice(const sp<DeviceDescriptor>& device,
                                                  audio_policy_dev_state_t state)
{
    sp<AudioInputDescriptor> desc;

    if (audio_device_is_digital(device->type())) {
        // erase all current sample rates, formats and channel masks
        device->clearAudioProfiles();
    }

    if (state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
        sp<AudioInputDescriptor> desc;

        // first call getAudioPort to get the supported attributes from the HAL
        struct audio_port_v7 port = {};
        device->toAudioPort(&port);
@@ -6704,6 +6710,11 @@ status_t AudioPolicyManager::checkInputsForDevice(const sp<DeviceDescriptor>& de
                    device->importAudioPortAndPickAudioProfile(profile);
                }
                ALOGV("checkInputsForDevice(): adding input %d", input);

                if (checkCloseInput(desc)) {
                    ALOGV("%s closing input %d", __func__, input);
                    closeInput(input);
                }
            }
        } // end scan profiles

@@ -7675,9 +7686,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 |
@@ -7694,18 +7702,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,
@@ -7714,7 +7729,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
@@ -526,6 +526,7 @@ protected:
        void addOutput(audio_io_handle_t output, const sp<SwAudioOutputDescriptor>& outputDesc);
        void removeOutput(audio_io_handle_t output);
        void addInput(audio_io_handle_t input, const sp<AudioInputDescriptor>& inputDesc);
        bool checkCloseInput(const sp<AudioInputDescriptor>& input);

        /**
         * @brief setOutputDevices change the route of the specified output.
+19 −0
Original line number Diff line number Diff line
@@ -70,6 +70,22 @@ public:
            return BAD_VALUE;
        }
        *input = mNextIoHandle++;
        mOpenedInputs.insert(*input);
        ALOGD("%s: opened input %d", __func__, *input);
        return NO_ERROR;
    }

    status_t closeInput(audio_io_handle_t input) override {
        if (mOpenedInputs.erase(input) != 1) {
            if (input >= mNextIoHandle) {
                ALOGE("%s: I/O handle %d has not been allocated yet (next is %d)",
                      __func__, input, mNextIoHandle);
            } else {
                ALOGE("%s: Attempt to close input %d twice", __func__, input);
            }
            return BAD_VALUE;
        }
        ALOGD("%s: closed input %d", __func__, input);
        return NO_ERROR;
    }

@@ -124,6 +140,8 @@ public:
        return &it->second;
    };

    size_t getOpenedInputsCount() const { return mOpenedInputs.size(); }

    audio_module_handle_t peekNextModuleHandle() const { return mNextModuleHandle; }

    void swapAllowedModuleNames(std::set<std::string>&& names = {}) {
@@ -241,6 +259,7 @@ private:
    std::vector<struct audio_port_v7> mDisconnectedDevicePorts;
    std::set<audio_format_t> mSupportedFormats;
    std::set<audio_channel_mask_t> mSupportedChannelMasks;
    std::set<audio_io_handle_t> mOpenedInputs;
};

} // namespace android
Loading