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

Commit 913d06c0 authored by Mikhail Naganov's avatar Mikhail Naganov
Browse files

Move TypeConverter into a shared library

This will be needed for the default implementation of the audio HAL
in TREBLE for parsing supported formats etc. provided by HAL in
a form of string literals.

As a bonus, remove some hand-written type conversions in AudioFlinger
used in dumps.

Example changes in the dump output:

   HAL format: 0x1 (pcm16) ==> HAL format: 0x1 (AUDIO_FORMAT_PCM_16_BIT)
   Processing format: 0x5 (pcmfloat) ==> Processing format: 0x5 (AUDIO_FORMAT_PCM_FLOAT)
   Output device: 0x2 (SPEAKER) ==> Output device: 0x2 (AUDIO_DEVICE_OUT_SPEAKER)
   Input device: 0 (NONE) ==> Input device: 0 (AUDIO_DEVICE_NONE)
   AudioStreamOut: 0x... flags 0x6 (PRIMARY|FAST) ==>
       AudioStreamOut: 0x... flags 0x6 (AUDIO_OUTPUT_FLAG_PRIMARY|AUDIO_OUTPUT_FLAG_FAST)

Test: make & run
Change-Id: I9cde640e6827b7aa6d62e9caade9e738227e299f
parent 267e07cd
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -75,7 +75,7 @@ public:

    static const char * const valueListSeparator;

    String8 toString();
    String8 toString() const;

    status_t add(const String8& key, const String8& value);
    status_t addInt(const String8& key, const int value);
@@ -83,12 +83,12 @@ public:

    status_t remove(const String8& key);

    status_t get(const String8& key, String8& value);
    status_t getInt(const String8& key, int& value);
    status_t getFloat(const String8& key, float& value);
    status_t getAt(size_t index, String8& key, String8& value);
    status_t get(const String8& key, String8& value) const;
    status_t getInt(const String8& key, int& value) const;
    status_t getFloat(const String8& key, float& value) const;
    status_t getAt(size_t index, String8& key, String8& value) const;

    size_t size() { return mParameters.size(); }
    size_t size() const { return mParameters.size(); }

private:
    String8 mKeyValuePairs;
+245 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ANDROID_TYPE_CONVERTER_H_
#define ANDROID_TYPE_CONVERTER_H_

#include <string>
#include <string.h>

#include <system/audio.h>
#include <utils/Log.h>
#include <utils/Vector.h>
#include <utils/SortedVector.h>

#include "convert.h"
#include "AudioParameter.h"

namespace android {

struct SampleRateTraits
{
    typedef uint32_t Type;
    typedef SortedVector<Type> Collection;
};
struct DeviceTraits
{
    typedef audio_devices_t Type;
    typedef Vector<Type> Collection;
};
struct OutputDeviceTraits : public DeviceTraits {};
struct InputDeviceTraits : public DeviceTraits {};
struct OutputFlagTraits
{
    typedef audio_output_flags_t Type;
    typedef Vector<Type> Collection;
};
struct InputFlagTraits
{
    typedef audio_input_flags_t Type;
    typedef Vector<Type> Collection;
};
struct FormatTraits
{
    typedef audio_format_t Type;
    typedef Vector<Type> Collection;
};
struct ChannelTraits
{
    typedef audio_channel_mask_t Type;
    typedef SortedVector<Type> Collection;
};
struct OutputChannelTraits : public ChannelTraits {};
struct InputChannelTraits : public ChannelTraits {};
struct ChannelIndexTraits : public ChannelTraits {};
struct GainModeTraits
{
    typedef audio_gain_mode_t Type;
    typedef Vector<Type> Collection;
};
struct StreamTraits
{
    typedef audio_stream_type_t Type;
    typedef Vector<Type> Collection;
};
struct AudioModeTraits
{
    typedef audio_mode_t Type;
    typedef Vector<Type> Collection;
};
template <typename T>
struct DefaultTraits
{
    typedef T Type;
    typedef Vector<Type> Collection;
};

template <class Traits>
static void collectionFromString(const std::string &str, typename Traits::Collection &collection,
                                 const char *del = AudioParameter::valueListSeparator)
{
    char *literal = strdup(str.c_str());
    for (const char *cstr = strtok(literal, del); cstr != NULL; cstr = strtok(NULL, del)) {
        typename Traits::Type value;
        if (utilities::convertTo<std::string, typename Traits::Type >(cstr, value)) {
            collection.add(value);
        }
    }
    free(literal);
}

template <class Traits>
class TypeConverter
{
public:
    static bool toString(const typename Traits::Type &value, std::string &str);

    static bool fromString(const std::string &str, typename Traits::Type &result);

    static void collectionFromString(const std::string &str,
                                     typename Traits::Collection &collection,
                                     const char *del = AudioParameter::valueListSeparator);

    static uint32_t maskFromString(
            const std::string &str, const char *del = AudioParameter::valueListSeparator);

    static void maskToString(
            uint32_t mask, std::string &str, const char *del = AudioParameter::valueListSeparator);

protected:
    struct Table {
        const char *literal;
        typename Traits::Type value;
    };

    static const Table mTable[];
};

template <class Traits>
inline bool TypeConverter<Traits>::toString(const typename Traits::Type &value, std::string &str)
{
    for (size_t i = 0; mTable[i].literal; i++) {
        if (mTable[i].value == value) {
            str = mTable[i].literal;
            return true;
        }
    }
    char result[64];
    snprintf(result, sizeof(result), "Unknown enum value %d", value);
    str = result;
    return false;
}

template <class Traits>
inline bool TypeConverter<Traits>::fromString(const std::string &str, typename Traits::Type &result)
{
    for (size_t i = 0; mTable[i].literal; i++) {
        if (strcmp(mTable[i].literal, str.c_str()) == 0) {
            ALOGV("stringToEnum() found %s", mTable[i].literal);
            result = mTable[i].value;
            return true;
        }
    }
    return false;
}

template <class Traits>
inline void TypeConverter<Traits>::collectionFromString(const std::string &str,
        typename Traits::Collection &collection,
        const char *del)
{
    char *literal = strdup(str.c_str());

    for (const char *cstr = strtok(literal, del); cstr != NULL; cstr = strtok(NULL, del)) {
        typename Traits::Type value;
        if (fromString(cstr, value)) {
            collection.add(value);
        }
    }
    free(literal);
}

template <class Traits>
inline uint32_t TypeConverter<Traits>::maskFromString(const std::string &str, const char *del)
{
    char *literal = strdup(str.c_str());
    uint32_t value = 0;
    for (const char *cstr = strtok(literal, del); cstr != NULL; cstr = strtok(NULL, del)) {
        typename Traits::Type type;
        if (fromString(cstr, type)) {
            value |= static_cast<uint32_t>(type);
        }
    }
    free(literal);
    return value;
}

template <class Traits>
inline void TypeConverter<Traits>::maskToString(uint32_t mask, std::string &str, const char *del)
{
    if (mask != 0) {
        bool first_flag = true;
        for (size_t i = 0; mTable[i].literal; i++) {
            if (mTable[i].value != 0 && (mask & mTable[i].value) == mTable[i].value) {
                if (!first_flag) str += del;
                first_flag = false;
                str += mTable[i].literal;
            }
        }
    } else {
        toString(static_cast<typename Traits::Type>(0), str);
    }
}

typedef TypeConverter<OutputDeviceTraits> OutputDeviceConverter;
typedef TypeConverter<InputDeviceTraits> InputDeviceConverter;
typedef TypeConverter<OutputFlagTraits> OutputFlagConverter;
typedef TypeConverter<InputFlagTraits> InputFlagConverter;
typedef TypeConverter<FormatTraits> FormatConverter;
typedef TypeConverter<OutputChannelTraits> OutputChannelConverter;
typedef TypeConverter<InputChannelTraits> InputChannelConverter;
typedef TypeConverter<ChannelIndexTraits> ChannelIndexConverter;
typedef TypeConverter<GainModeTraits> GainModeConverter;
typedef TypeConverter<StreamTraits> StreamTypeConverter;
typedef TypeConverter<AudioModeTraits> AudioModeConverter;

bool deviceFromString(const std::string& literalDevice, audio_devices_t& device);

bool deviceToString(audio_devices_t device, std::string& literalDevice);

SampleRateTraits::Collection samplingRatesFromString(
        const std::string &samplingRates, const char *del = AudioParameter::valueListSeparator);

FormatTraits::Collection formatsFromString(
        const std::string &formats, const char *del = AudioParameter::valueListSeparator);

audio_format_t formatFromString(
        const std::string &literalFormat, audio_format_t defaultFormat = AUDIO_FORMAT_DEFAULT);

audio_channel_mask_t channelMaskFromString(const std::string &literalChannels);

ChannelTraits::Collection channelMasksFromString(
        const std::string &channels, const char *del = AudioParameter::valueListSeparator);

InputChannelTraits::Collection inputChannelMasksFromString(
        const std::string &inChannels, const char *del = AudioParameter::valueListSeparator);

OutputChannelTraits::Collection outputChannelMasksFromString(
        const std::string &outChannels, const char *del = AudioParameter::valueListSeparator);

}; // namespace android

#endif  /*ANDROID_TYPE_CONVERTER_H_*/
+1 −1
Original line number Diff line number Diff line
cc_library_static {
    name: "libmedia_helper",
    srcs: ["AudioParameter.cpp"],
    srcs: ["AudioParameter.cpp", "TypeConverter.cpp"],
    cflags: [
        "-Werror",
        "-Wno-error=deprecated-declarations",
+5 −5
Original line number Diff line number Diff line
@@ -83,7 +83,7 @@ AudioParameter::~AudioParameter()
    mParameters.clear();
}

String8 AudioParameter::toString()
String8 AudioParameter::toString() const
{
    String8 str = String8("");

@@ -140,7 +140,7 @@ status_t AudioParameter::remove(const String8& key)
    }
}

status_t AudioParameter::get(const String8& key, String8& value)
status_t AudioParameter::get(const String8& key, String8& value) const
{
    if (mParameters.indexOfKey(key) >= 0) {
        value = mParameters.valueFor(key);
@@ -150,7 +150,7 @@ status_t AudioParameter::get(const String8& key, String8& value)
    }
}

status_t AudioParameter::getInt(const String8& key, int& value)
status_t AudioParameter::getInt(const String8& key, int& value) const
{
    String8 str8;
    status_t result = get(key, str8);
@@ -166,7 +166,7 @@ status_t AudioParameter::getInt(const String8& key, int& value)
    return result;
}

status_t AudioParameter::getFloat(const String8& key, float& value)
status_t AudioParameter::getFloat(const String8& key, float& value) const
{
    String8 str8;
    status_t result = get(key, str8);
@@ -182,7 +182,7 @@ status_t AudioParameter::getFloat(const String8& key, float& value)
    return result;
}

status_t AudioParameter::getAt(size_t index, String8& key, String8& value)
status_t AudioParameter::getAt(size_t index, String8& key, String8& value) const
{
    if (mParameters.size() > index) {
        key = mParameters.keyAt(index);
Loading