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

Commit 14662b57 authored by jiabin's avatar jiabin
Browse files

Support device role for capture preset.

When preferred device(s) is set for capture preset, use it as input
device if it is currently available. Remove the disabled device from the
availale device list.

Bug: 271412776
Test: atest audiopolicy_tests
Change-Id: Ia8750d75bddef11dcb0aaf0d0b91f2e24f714775
parent fa98e2e3
Loading
Loading
Loading
Loading
+45 −0
Original line number Diff line number Diff line
@@ -479,6 +479,37 @@ DeviceVector Engine::getDevicesForStrategyInt(legacy_strategy strategy,
    return devices;
}

DeviceVector Engine::getPreferredAvailableDevicesForInputSource(
            const DeviceVector& availableInputDevices, audio_source_t inputSource) const {
    DeviceVector preferredAvailableDevVec = {};
    AudioDeviceTypeAddrVector preferredDevices;
    const status_t status = getDevicesForRoleAndCapturePreset(
            inputSource, DEVICE_ROLE_PREFERRED, preferredDevices);
    if (status == NO_ERROR) {
        // Only use preferred devices when they are all available.
        preferredAvailableDevVec =
                availableInputDevices.getDevicesFromDeviceTypeAddrVec(preferredDevices);
        if (preferredAvailableDevVec.size() == preferredDevices.size()) {
            ALOGVV("%s using pref device %s for source %u",
                   __func__, preferredAvailableDevVec.toString().c_str(), inputSource);
            return preferredAvailableDevVec;
        }
    }
    return preferredAvailableDevVec;
}

DeviceVector Engine::getDisabledDevicesForInputSource(
            const DeviceVector& availableInputDevices, audio_source_t inputSource) const {
    DeviceVector disabledDevices = {};
    AudioDeviceTypeAddrVector disabledDevicesTypeAddr;
    const status_t status = getDevicesForRoleAndCapturePreset(
            inputSource, DEVICE_ROLE_DISABLED, disabledDevicesTypeAddr);
    if (status == NO_ERROR) {
        disabledDevices =
                availableInputDevices.getDevicesFromDeviceTypeAddrVec(disabledDevicesTypeAddr);
    }
    return disabledDevices;
}

sp<DeviceDescriptor> Engine::getDeviceForInputSource(audio_source_t inputSource) const
{
@@ -510,6 +541,20 @@ sp<DeviceDescriptor> Engine::getDeviceForInputSource(audio_source_t inputSource)
        }
    }

    // Use the preferred device for the input source if it is available.
    DeviceVector preferredInputDevices = getPreferredAvailableDevicesForInputSource(
            availableDevices, inputSource);
    if (!preferredInputDevices.isEmpty()) {
        // Currently, only support single device for input. The public JAVA API also only
        // support setting single device as preferred device. In that case, returning the
        // first device is OK here.
        return preferredInputDevices[0];
    }
    // Remove the disabled device for the input source from the available input device list.
    DeviceVector disabledInputDevices = getDisabledDevicesForInputSource(
            availableDevices, inputSource);
    availableDevices.remove(disabledInputDevices);

    audio_devices_t commDeviceType =
        getPreferredDeviceTypeForLegacyStrategy(availableOutputDevices, STRATEGY_PHONE);

+4 −0
Original line number Diff line number Diff line
@@ -99,6 +99,10 @@ private:
        const DeviceVector& availableOutputDevices, product_strategy_t strategy) const;
    DeviceVector getDisabledDevicesForProductStrategy(
        const DeviceVector& availableOutputDevices, product_strategy_t strategy) const;
    DeviceVector getPreferredAvailableDevicesForInputSource(
            const DeviceVector& availableInputDevices, audio_source_t inputSource) const;
    DeviceVector getDisabledDevicesForInputSource(
            const DeviceVector& availableInputDevices, audio_source_t inputSource) const;

    DeviceStrategyMap mDevicesForStrategies;

+102 −0
Original line number Diff line number Diff line
@@ -2833,6 +2833,108 @@ TEST_P(AudioPolicyManagerDevicesRoleForCapturePresetTest, DevicesRoleForCaptureP
              mManager->getDevicesForRoleAndCapturePreset(audioSource, role, devices));
}

TEST_F(AudioPolicyManagerDevicesRoleForCapturePresetTest, PreferredDeviceUsedForInput) {
    const audio_source_t source = AUDIO_SOURCE_MIC;
    const device_role_t role = DEVICE_ROLE_PREFERRED;
    const std::string address = "card=1;device=0";
    const std::string deviceName = "randomName";

    ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(
            AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
            address.c_str(), deviceName.c_str(), AUDIO_FORMAT_DEFAULT));
    auto availableDevices = mManager->getAvailableInputDevices();
    ASSERT_GT(availableDevices.size(), 1);

    audio_attributes_t attr = AUDIO_ATTRIBUTES_INITIALIZER;
    attr.source = source;
    audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
    ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, AUDIO_SESSION_NONE, 1, &selectedDeviceId,
                                            AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO,
                                            48000));
    auto selectedDevice = availableDevices.getDeviceFromId(selectedDeviceId);
    ASSERT_NE(nullptr, selectedDevice);

    sp<DeviceDescriptor> preferredDevice = nullptr;
    for (const auto& device : availableDevices) {
        if (device != selectedDevice) {
            preferredDevice = device;
            break;
        }
    }
    ASSERT_NE(nullptr, preferredDevice);
    // After setting preferred device for capture preset, the selected device for input should be
    // the preferred device.
    ASSERT_EQ(NO_ERROR,
              mManager->setDevicesRoleForCapturePreset(source, role,
                                                       {preferredDevice->getDeviceTypeAddr()}));
    selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
    ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, AUDIO_SESSION_NONE, 1, &selectedDeviceId,
                                            AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO,
                                            48000));
    ASSERT_EQ(preferredDevice, availableDevices.getDeviceFromId(selectedDeviceId));

    // After clearing preferred device for capture preset, the selected device for input should be
    // the same as original one.
    ASSERT_EQ(NO_ERROR,
              mManager->clearDevicesRoleForCapturePreset(source, role));
    selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
    ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, AUDIO_SESSION_NONE, 1, &selectedDeviceId,
                                            AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO,
                                            48000));
    ASSERT_EQ(selectedDevice, availableDevices.getDeviceFromId(selectedDeviceId));

    ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(
            AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
            address.c_str(), deviceName.c_str(), AUDIO_FORMAT_DEFAULT));
}

TEST_F(AudioPolicyManagerDevicesRoleForCapturePresetTest, DisabledDeviceNotUsedForInput) {
    const audio_source_t source = AUDIO_SOURCE_MIC;
    const device_role_t role = DEVICE_ROLE_DISABLED;
    const std::string address = "card=1;device=0";
    const std::string deviceName = "randomName";

    ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(
            AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
            address.c_str(), deviceName.c_str(), AUDIO_FORMAT_DEFAULT));
    auto availableDevices = mManager->getAvailableInputDevices();
    ASSERT_GT(availableDevices.size(), 1);

    audio_attributes_t attr = AUDIO_ATTRIBUTES_INITIALIZER;
    attr.source = source;
    audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
    ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, AUDIO_SESSION_NONE, 1, &selectedDeviceId,
                                            AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO,
                                            48000));
    auto selectedDevice = availableDevices.getDeviceFromId(selectedDeviceId);
    ASSERT_NE(nullptr, selectedDevice);

    // After setting disabled device for capture preset, the disabled device must not be
    // selected for input.
    ASSERT_EQ(NO_ERROR,
              mManager->setDevicesRoleForCapturePreset(source, role,
                                                       {selectedDevice->getDeviceTypeAddr()}));
    selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
    ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, AUDIO_SESSION_NONE, 1, &selectedDeviceId,
                                            AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO,
                                            48000));
    ASSERT_NE(selectedDevice, availableDevices.getDeviceFromId(selectedDeviceId));

    // After clearing disabled device for capture preset, the selected device for input should be
    // the original one.
    ASSERT_EQ(NO_ERROR,
              mManager->clearDevicesRoleForCapturePreset(source, role));
    selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
    ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, AUDIO_SESSION_NONE, 1, &selectedDeviceId,
                                            AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO,
                                            48000));
    ASSERT_EQ(selectedDevice, availableDevices.getDeviceFromId(selectedDeviceId));

    ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(
            AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
            address.c_str(), deviceName.c_str(), AUDIO_FORMAT_DEFAULT));
}

INSTANTIATE_TEST_CASE_P(
        DevicesRoleForCapturePresetOperation,
        AudioPolicyManagerDevicesRoleForCapturePresetTest,
+3 −1
Original line number Diff line number Diff line
@@ -77,12 +77,14 @@
                </devicePort>
                <devicePort tagName="USB Device Out" type="AUDIO_DEVICE_OUT_USB_DEVICE" role="sink">
                </devicePort>
                <devicePort tagName="USB Device In" type="AUDIO_DEVICE_IN_USB_DEVICE" role="source">
                </devicePort>
            </devicePorts>
            <routes>
                <route type="mix" sink="Speaker"
                       sources="primary output,voip_rx"/>
                <route type="mix" sink="primary input"
                       sources="Built-In Mic,Hdmi-In Mic"/>
                       sources="Built-In Mic,Hdmi-In Mic,USB Device In"/>
                <route type="mix" sink="voip_tx"
                       sources="Built-In Mic"/>
                <route type="mix" sink="Hdmi"