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

Commit 5dbe4713 authored by Eric Laurent's avatar Eric Laurent
Browse files

audio policy: add hw hotword flag for inputs

Audio input profiles can indicate flag AUDIO_INPUT_FLAG_HW_HOTWORD
meaning they allow capture from the same source as HW hotword
detection.

When a client requests capture with this flag, the policy will
try to find an input profile matching this request first and
fallback to a regular input if not found.

Bug: 17575019.
Change-Id: Ia463211597d7fa363527d776389f2257f0ced9a2
parent b0ed4e3e
Loading
Loading
Loading
Loading
+64 −27
Original line number Diff line number Diff line
@@ -112,7 +112,7 @@ const StringToEnum sDeviceNameToEnumTable[] = {
    STRING_TO_ENUM(AUDIO_DEVICE_IN_LOOPBACK),
};

const StringToEnum sFlagNameToEnumTable[] = {
const StringToEnum sOutputFlagNameToEnumTable[] = {
    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DIRECT),
    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_PRIMARY),
    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_FAST),
@@ -122,6 +122,11 @@ const StringToEnum sFlagNameToEnumTable[] = {
    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_HW_AV_SYNC),
};

const StringToEnum sInputFlagNameToEnumTable[] = {
    STRING_TO_ENUM(AUDIO_INPUT_FLAG_FAST),
    STRING_TO_ENUM(AUDIO_INPUT_FLAG_HW_HOTWORD),
};

const StringToEnum sFormatNameToEnumTable[] = {
    STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
    STRING_TO_ENUM(AUDIO_FORMAT_PCM_8_BIT),
@@ -1292,17 +1297,42 @@ audio_io_handle_t AudioPolicyManager::getInput(audio_source_t inputSource,
        break;
    }

    audio_io_handle_t input = AUDIO_IO_HANDLE_NONE;
    bool isSoundTrigger = false;
    audio_source_t halInputSource = inputSource;
    if (inputSource == AUDIO_SOURCE_HOTWORD) {
        ssize_t index = mSoundTriggerSessions.indexOfKey(session);
        if (index >= 0) {
            input = mSoundTriggerSessions.valueFor(session);
            isSoundTrigger = true;
            flags = (audio_input_flags_t)(flags | AUDIO_INPUT_FLAG_HW_HOTWORD);
            ALOGV("SoundTrigger capture on session %d input %d", session, input);
        } else {
            halInputSource = AUDIO_SOURCE_VOICE_RECOGNITION;
        }
    }

    sp<IOProfile> profile = getInputProfile(device,
                                         samplingRate,
                                         format,
                                         channelMask,
                                         flags);
    if (profile == 0) {
        //retry without flags
        audio_input_flags_t log_flags = flags;
        flags = AUDIO_INPUT_FLAG_NONE;
        profile = getInputProfile(device,
                                 samplingRate,
                                 format,
                                 channelMask,
                                 flags);
        if (profile == 0) {
            ALOGW("getInput() could not find profile for device 0x%X, samplingRate %u, format %#x, "
                    "channelMask 0x%X, flags %#x",
                device, samplingRate, format, channelMask, flags);
                    device, samplingRate, format, channelMask, log_flags);
            return AUDIO_IO_HANDLE_NONE;
        }
    }

    if (profile->mModule->mHandle == 0) {
        ALOGE("getInput(): HW module %s not opened", profile->mModule->mName);
@@ -1313,20 +1343,7 @@ audio_io_handle_t AudioPolicyManager::getInput(audio_source_t inputSource,
    config.sample_rate = samplingRate;
    config.channel_mask = channelMask;
    config.format = format;
    audio_io_handle_t input = AUDIO_IO_HANDLE_NONE;

    bool isSoundTrigger = false;
    audio_source_t halInputSource = inputSource;
    if (inputSource == AUDIO_SOURCE_HOTWORD) {
        ssize_t index = mSoundTriggerSessions.indexOfKey(session);
        if (index >= 0) {
            input = mSoundTriggerSessions.valueFor(session);
            isSoundTrigger = true;
            ALOGV("SoundTrigger capture on session %d input %d", session, input);
        } else {
            halInputSource = AUDIO_SOURCE_VOICE_RECOGNITION;
        }
    }
    status_t status = mpClientInterface->openInput(profile->mModule->mHandle,
                                                   &input,
                                                   &config,
@@ -5220,7 +5237,7 @@ AudioPolicyManager::AudioOutputDescriptor::AudioOutputDescriptor(
        mStrategyMutedByDevice[i] = false;
    }
    if (profile != NULL) {
        mFlags = profile->mFlags;
        mFlags = (audio_output_flags_t)profile->mFlags;
        mSamplingRate = profile->pickSamplingRate();
        mFormat = profile->pickFormat();
        mChannelMask = profile->pickChannelMask();
@@ -5568,6 +5585,8 @@ status_t AudioPolicyManager::HwModule::loadInput(cnode *root)
        } else if (strcmp(node->name, DEVICES_TAG) == 0) {
            profile->mSupportedDevices.loadDevicesFromName((char *)node->value,
                                                           mDeclaredDevices);
        } else if (strcmp(node->name, FLAGS_TAG) == 0) {
            profile->mFlags = parseInputFlagNames((char *)node->value);
        } else if (strcmp(node->name, GAINS_TAG) == 0) {
            profile->loadGains(node);
        }
@@ -5613,7 +5632,7 @@ status_t AudioPolicyManager::HwModule::loadOutput(cnode *root)
            profile->mSupportedDevices.loadDevicesFromName((char *)node->value,
                                                           mDeclaredDevices);
        } else if (strcmp(node->name, FLAGS_TAG) == 0) {
            profile->mFlags = parseFlagNames((char *)node->value);
            profile->mFlags = parseOutputFlagNames((char *)node->value);
        } else if (strcmp(node->name, GAINS_TAG) == 0) {
            profile->loadGains(node);
        }
@@ -5728,7 +5747,7 @@ void AudioPolicyManager::HwModule::dump(int fd)

AudioPolicyManager::AudioPort::AudioPort(const String8& name, audio_port_type_t type,
          audio_port_role_t role, const sp<HwModule>& module) :
    mName(name), mType(type), mRole(role), mModule(module), mFlags((audio_output_flags_t)0)
    mName(name), mType(type), mRole(role), mModule(module), mFlags(0)
{
    mUseInChannelMask = ((type == AUDIO_PORT_TYPE_DEVICE) && (role == AUDIO_PORT_ROLE_SOURCE)) ||
                    ((type == AUDIO_PORT_TYPE_MIX) && (role == AUDIO_PORT_ROLE_SINK));
@@ -6560,7 +6579,7 @@ bool AudioPolicyManager::IOProfile::isCompatibleProfile(audio_devices_t device,
                                                            uint32_t *updatedSamplingRate,
                                                            audio_format_t format,
                                                            audio_channel_mask_t channelMask,
                                                            audio_output_flags_t flags) const
                                                            uint32_t flags) const
{
    const bool isPlaybackThread = mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SOURCE;
    const bool isRecordThread = mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SINK;
@@ -6602,7 +6621,7 @@ bool AudioPolicyManager::IOProfile::isCompatibleProfile(audio_devices_t device,
    // An existing fast stream is compatible with a normal track request.
    // An existing normal stream is compatible with a fast track request,
    // but the fast request will be denied by AudioFlinger and converted to normal track.
    if (isRecordThread && (((audio_input_flags_t) mFlags ^ (audio_input_flags_t) flags) &
    if (isRecordThread && ((mFlags ^ flags) &
            ~AUDIO_INPUT_FLAG_FAST)) {
        return false;
    }
@@ -6958,7 +6977,7 @@ status_t AudioPolicyManager::AudioPatch::dump(int fd, int spaces, int index) con

// --- audio_policy.conf file parsing

audio_output_flags_t AudioPolicyManager::parseFlagNames(char *name)
uint32_t AudioPolicyManager::parseOutputFlagNames(char *name)
{
    uint32_t flag = 0;

@@ -6967,8 +6986,8 @@ audio_output_flags_t AudioPolicyManager::parseFlagNames(char *name)
    char *flagName = strtok(name, "|");
    while (flagName != NULL) {
        if (strlen(flagName) != 0) {
            flag |= stringToEnum(sFlagNameToEnumTable,
                               ARRAY_SIZE(sFlagNameToEnumTable),
            flag |= stringToEnum(sOutputFlagNameToEnumTable,
                               ARRAY_SIZE(sOutputFlagNameToEnumTable),
                               flagName);
        }
        flagName = strtok(NULL, "|");
@@ -6980,7 +6999,25 @@ audio_output_flags_t AudioPolicyManager::parseFlagNames(char *name)
        flag |= AUDIO_OUTPUT_FLAG_DIRECT;
    }

    return (audio_output_flags_t)flag;
    return flag;
}

uint32_t AudioPolicyManager::parseInputFlagNames(char *name)
{
    uint32_t flag = 0;

    // it is OK to cast name to non const here as we are not going to use it after
    // strtok() modifies it
    char *flagName = strtok(name, "|");
    while (flagName != NULL) {
        if (strlen(flagName) != 0) {
            flag |= stringToEnum(sInputFlagNameToEnumTable,
                               ARRAY_SIZE(sInputFlagNameToEnumTable),
                               flagName);
        }
        flagName = strtok(NULL, "|");
    }
    return flag;
}

audio_devices_t AudioPolicyManager::parseDeviceNames(char *name)
+5 −4
Original line number Diff line number Diff line
@@ -283,8 +283,8 @@ protected:
            Vector <audio_format_t> mFormats; // supported audio formats
            Vector < sp<AudioGain> > mGains; // gain controllers
            sp<HwModule> mModule;                 // audio HW module exposing this I/O stream
            audio_output_flags_t mFlags; // attribute flags (e.g primary output,
                                                // direct output...). For outputs only.
            uint32_t mFlags; // attribute flags (e.g primary output,
                                                // direct output...).
        };

        class AudioPortConfig: public virtual RefBase
@@ -387,7 +387,7 @@ protected:
                                     uint32_t *updatedSamplingRate,
                                     audio_format_t format,
                                     audio_channel_mask_t channelMask,
                                     audio_output_flags_t flags) const;
                                     uint32_t flags) const;

            void dump(int fd);
            void log();
@@ -754,7 +754,8 @@ protected:
                                      size_t size,
                                      uint32_t value);
        static bool stringToBool(const char *value);
        static audio_output_flags_t parseFlagNames(char *name);
        static uint32_t parseOutputFlagNames(char *name);
        static uint32_t parseInputFlagNames(char *name);
        static audio_devices_t parseDeviceNames(char *name);
        void loadHwModule(cnode *root);
        void loadHwModules(cnode *root);