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

Commit b695746f authored by Mikhail Naganov's avatar Mikhail Naganov Committed by Cherrypicker Worker
Browse files

libaudiohal@aidl: Fix handling of point-to-point connections

Point-to-point connections (analog, HDMI, SPDIF) do not use
a device address. Reflect that in `GenerateUniqueDeviceAddress`.
When looking for a device port by address, check if there is
a connected device, and use the connected device port.

Bug: 300648357
Test: atest audiosystem_tests
(cherry picked from https://android-review.googlesource.com/q/commit:892f7614d957ad62a474c588e1d433962779c22c)
Merged-In: Ic89fe25f1b757d8d95da0cbef09aa55887e62f4f
Change-Id: Ic89fe25f1b757d8d95da0cbef09aa55887e62f4f
parent e001e618
Loading
Loading
Loading
Loading
+28 −19
Original line number Original line Diff line number Diff line
@@ -615,10 +615,18 @@ class WithSimulatedDeviceConnections {


android::media::audio::common::AudioPort GenerateUniqueDeviceAddress(
android::media::audio::common::AudioPort GenerateUniqueDeviceAddress(
        const android::media::audio::common::AudioPort& port) {
        const android::media::audio::common::AudioPort& port) {
    // Point-to-point connections do not use addresses.
    static const std::set<std::string> kPointToPointConnections = {
            AudioDeviceDescription::CONNECTION_ANALOG(), AudioDeviceDescription::CONNECTION_HDMI(),
            AudioDeviceDescription::CONNECTION_HDMI_ARC(),
            AudioDeviceDescription::CONNECTION_HDMI_EARC(),
            AudioDeviceDescription::CONNECTION_SPDIF()};
    static int nextId = 0;
    static int nextId = 0;
    using Tag = AudioDeviceAddress::Tag;
    using Tag = AudioDeviceAddress::Tag;
    const auto& deviceDescription = port.ext.get<AudioPortExt::Tag::device>().device.type;
    AudioDeviceAddress address;
    AudioDeviceAddress address;
    switch (suggestDeviceAddressTag(port.ext.get<AudioPortExt::Tag::device>().device.type)) {
    if (kPointToPointConnections.count(deviceDescription.connection) == 0) {
        switch (suggestDeviceAddressTag(deviceDescription)) {
            case Tag::id:
            case Tag::id:
                address = AudioDeviceAddress::make<Tag::id>(std::to_string(++nextId));
                address = AudioDeviceAddress::make<Tag::id>(std::to_string(++nextId));
                break;
                break;
@@ -638,6 +646,7 @@ android::media::audio::common::AudioPort GenerateUniqueDeviceAddress(
                address = AudioDeviceAddress::make<Tag::alsa>(std::vector<int32_t>{1, ++nextId});
                address = AudioDeviceAddress::make<Tag::alsa>(std::vector<int32_t>{1, ++nextId});
                break;
                break;
        }
        }
    }
    android::media::audio::common::AudioPort result = port;
    android::media::audio::common::AudioPort result = port;
    result.ext.get<AudioPortExt::Tag::device>().device.address = std::move(address);
    result.ext.get<AudioPortExt::Tag::device>().device.address = std::move(address);
    return result;
    return result;
+25 −5
Original line number Original line Diff line number Diff line
@@ -1099,6 +1099,7 @@ status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool
                "%s: module %s, duplicate port ID received from HAL: %s, existing port: %s",
                "%s: module %s, duplicate port ID received from HAL: %s, existing port: %s",
                __func__, mInstance.c_str(), connectedPort.toString().c_str(),
                __func__, mInstance.c_str(), connectedPort.toString().c_str(),
                it->second.toString().c_str());
                it->second.toString().c_str());
        mConnectedPorts[connectedPort.id] = false;
    } else {  // !connected
    } else {  // !connected
        AudioDevice matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
        AudioDevice matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
        auto portsIt = findPort(matchDevice);
        auto portsIt = findPort(matchDevice);
@@ -1118,10 +1119,11 @@ status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool
            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
                            mModule->disconnectExternalDevice(portId)));
                            mModule->disconnectExternalDevice(portId)));
            mPorts.erase(portsIt);
            mPorts.erase(portsIt);
            mConnectedPorts.erase(portId);
        } else {
        } else {
            ALOGD("%s: since device port ID %d is used by a stream, "
            ALOGD("%s: since device port ID %d is used by a stream, "
                    "external device disconnection postponed", __func__, portId);
                    "external device disconnection postponed", __func__, portId);
            mConnectedPortIdsHeldByStreams.insert(portId);
            mConnectedPorts[portId] = true;
        }
        }
    }
    }
    return updateRoutes();
    return updateRoutes();
@@ -1620,9 +1622,26 @@ DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(const AudioDevice& device
    } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
    } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
        return mPorts.find(mDefaultOutputPortId);
        return mPorts.find(mDefaultOutputPortId);
    }
    }
    if (device.address.getTag() != AudioDeviceAddress::id ||
            !device.address.get<AudioDeviceAddress::id>().empty()) {
        return std::find_if(mPorts.begin(), mPorts.end(),
        return std::find_if(mPorts.begin(), mPorts.end(),
                [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
                [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
    }
    }
    // For connection w/o an address, two ports can be found: the template port,
    // and a connected port (if exists). Make sure we return the connected port.
    DeviceHalAidl::Ports::iterator portIt = mPorts.end();
    for (auto it = mPorts.begin(); it != mPorts.end(); ++it) {
        if (audioDeviceMatches(device, it->second)) {
            if (mConnectedPorts.find(it->first) != mConnectedPorts.end()) {
                return it;
            } else {
                // Will return 'it' if there is no connected port.
                portIt = it;
            }
        }
    }
    return portIt;
}


DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
            const AudioConfig& config, const AudioIoFlags& flags,
            const AudioConfig& config, const AudioIoFlags& flags,
@@ -1784,7 +1803,8 @@ void DeviceHalAidl::resetUnusedPortConfigs() {
    std::set<int32_t> retryDeviceDisconnection;
    std::set<int32_t> retryDeviceDisconnection;
    for (const auto& portConfigAndIdPair : portConfigIds) {
    for (const auto& portConfigAndIdPair : portConfigIds) {
        resetPortConfig(portConfigAndIdPair.first);
        resetPortConfig(portConfigAndIdPair.first);
        if (mConnectedPortIdsHeldByStreams.count(portConfigAndIdPair.second) != 0) {
        if (const auto it = mConnectedPorts.find(portConfigAndIdPair.second);
                it != mConnectedPorts.end() && it->second) {
            retryDeviceDisconnection.insert(portConfigAndIdPair.second);
            retryDeviceDisconnection.insert(portConfigAndIdPair.second);
        }
        }
    }
    }
@@ -1793,7 +1813,7 @@ void DeviceHalAidl::resetUnusedPortConfigs() {
            TIME_CHECK();
            TIME_CHECK();
            if (auto status = mModule->disconnectExternalDevice(portId); status.isOk()) {
            if (auto status = mModule->disconnectExternalDevice(portId); status.isOk()) {
                mPorts.erase(portId);
                mPorts.erase(portId);
                mConnectedPortIdsHeldByStreams.erase(portId);
                mConnectedPorts.erase(portId);
                ALOGD("%s: executed postponed external device disconnection for port ID %d",
                ALOGD("%s: executed postponed external device disconnection for port ID %d",
                        __func__, portId);
                        __func__, portId);
            }
            }
+3 −1
Original line number Original line Diff line number Diff line
@@ -191,6 +191,8 @@ class DeviceHalAidl : public DeviceHalInterface, public ConversionHelperAidl,
        Status status = Status::UNKNOWN;
        Status status = Status::UNKNOWN;
        MicrophoneInfoProvider::Info info;
        MicrophoneInfoProvider::Info info;
    };
    };
    // IDs of ports for connected external devices, and whether they are held by streams.
    using ConnectedPorts = std::map<int32_t /*port ID*/, bool>;
    using Patches = std::map<int32_t /*patch ID*/,
    using Patches = std::map<int32_t /*patch ID*/,
            ::aidl::android::hardware::audio::core::AudioPatch>;
            ::aidl::android::hardware::audio::core::AudioPatch>;
    using PortConfigs = std::map<int32_t /*port config ID*/,
    using PortConfigs = std::map<int32_t /*port config ID*/,
@@ -319,7 +321,7 @@ class DeviceHalAidl : public DeviceHalInterface, public ConversionHelperAidl,
    std::mutex mLock;
    std::mutex mLock;
    std::map<void*, Callbacks> mCallbacks GUARDED_BY(mLock);
    std::map<void*, Callbacks> mCallbacks GUARDED_BY(mLock);
    std::set<audio_port_handle_t> mDeviceDisconnectionNotified;
    std::set<audio_port_handle_t> mDeviceDisconnectionNotified;
    std::set<int32_t> mConnectedPortIdsHeldByStreams;
    ConnectedPorts mConnectedPorts;
};
};


} // namespace android
} // namespace android