Mikhail Naganov | 6e81e9b | 2016-11-16 16:30:17 -0800 | [diff] [blame] | 1 | /* |
Kevin Rocard | 96d2cd9 | 2018-11-14 16:22:07 -0800 | [diff] [blame] | 2 | * Copyright (C) 2018 The Android Open Source Project |
Mikhail Naganov | 6e81e9b | 2016-11-16 16:30:17 -0800 | [diff] [blame] | 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
Kevin Rocard | 96d2cd9 | 2018-11-14 16:22:07 -0800 | [diff] [blame] | 17 | #ifndef android_hardware_audio_Hidl_Utils_H_ |
| 18 | #define android_hardware_audio_Hidl_Utils_H_ |
| 19 | |
| 20 | #include PATH(android/hardware/audio/common/FILE_VERSION/types.h) |
Mikhail Naganov | 6e81e9b | 2016-11-16 16:30:17 -0800 | [diff] [blame] | 21 | |
| 22 | #include <memory> |
| 23 | |
Mikhail Naganov | 6e81e9b | 2016-11-16 16:30:17 -0800 | [diff] [blame] | 24 | #include <system/audio.h> |
| 25 | |
Mikhail Naganov | 6e81e9b | 2016-11-16 16:30:17 -0800 | [diff] [blame] | 26 | namespace android { |
Kevin Rocard | 6891d7e | 2017-12-14 18:39:39 -0800 | [diff] [blame] | 27 | namespace hardware { |
| 28 | namespace audio { |
| 29 | namespace common { |
Kevin Rocard | 96d2cd9 | 2018-11-14 16:22:07 -0800 | [diff] [blame] | 30 | namespace CPP_VERSION { |
Mikhail Naganov | 543bf9c | 2018-12-11 16:36:53 -0800 | [diff] [blame] | 31 | namespace implementation { |
| 32 | |
Mikhail Naganov | b52e93f | 2020-12-10 16:10:08 -0800 | [diff] [blame^] | 33 | using ::android::hardware::hidl_vec; |
Mikhail Naganov | 543bf9c | 2018-12-11 16:36:53 -0800 | [diff] [blame] | 34 | using namespace ::android::hardware::audio::common::CPP_VERSION; |
Mikhail Naganov | 6e81e9b | 2016-11-16 16:30:17 -0800 | [diff] [blame] | 35 | |
Mikhail Naganov | 1b444a5 | 2020-10-29 13:08:05 -0700 | [diff] [blame] | 36 | struct HidlUtils { |
Mikhail Naganov | 1b444a5 | 2020-10-29 13:08:05 -0700 | [diff] [blame] | 37 | static status_t audioConfigFromHal(const audio_config_t& halConfig, bool isInput, |
| 38 | AudioConfig* config); |
Mikhail Naganov | b52e93f | 2020-12-10 16:10:08 -0800 | [diff] [blame^] | 39 | static status_t audioConfigToHal(const AudioConfig& config, audio_config_t* halConfig); |
| 40 | #if MAJOR_VERSION >= 4 |
| 41 | static status_t audioContentTypeFromHal(const audio_content_type_t halContentType, |
| 42 | AudioContentType* contentType); |
| 43 | static status_t audioContentTypeToHal(const AudioContentType& contentType, |
| 44 | audio_content_type_t* halContentType); |
| 45 | #endif |
Mikhail Naganov | 1b444a5 | 2020-10-29 13:08:05 -0700 | [diff] [blame] | 46 | static status_t audioGainConfigFromHal(const struct audio_gain_config& halConfig, bool isInput, |
| 47 | AudioGainConfig* config); |
Mikhail Naganov | 1b444a5 | 2020-10-29 13:08:05 -0700 | [diff] [blame] | 48 | static status_t audioGainConfigToHal(const AudioGainConfig& config, |
| 49 | struct audio_gain_config* halConfig); |
Mikhail Naganov | b52e93f | 2020-12-10 16:10:08 -0800 | [diff] [blame^] | 50 | static status_t audioGainFromHal(const struct audio_gain& halGain, bool isInput, |
| 51 | AudioGain* gain); |
Mikhail Naganov | 1b444a5 | 2020-10-29 13:08:05 -0700 | [diff] [blame] | 52 | static status_t audioGainToHal(const AudioGain& gain, struct audio_gain* halGain); |
| 53 | static status_t audioUsageFromHal(audio_usage_t halUsage, AudioUsage* usage); |
| 54 | static status_t audioUsageToHal(const AudioUsage& usage, audio_usage_t* halUsage); |
Andy Hung | 7aab101 | 2020-02-14 15:39:55 -0800 | [diff] [blame] | 55 | static status_t audioOffloadInfoFromHal(const audio_offload_info_t& halOffload, |
| 56 | AudioOffloadInfo* offload); |
Mikhail Naganov | 1b444a5 | 2020-10-29 13:08:05 -0700 | [diff] [blame] | 57 | static status_t audioOffloadInfoToHal(const AudioOffloadInfo& offload, |
| 58 | audio_offload_info_t* halOffload); |
| 59 | static status_t audioPortConfigFromHal(const struct audio_port_config& halConfig, |
| 60 | AudioPortConfig* config); |
| 61 | static status_t audioPortConfigToHal(const AudioPortConfig& config, |
| 62 | struct audio_port_config* halConfig); |
| 63 | static status_t audioPortConfigsFromHal(unsigned int numHalConfigs, |
| 64 | const struct audio_port_config* halConfigs, |
Mikhail Naganov | b52e93f | 2020-12-10 16:10:08 -0800 | [diff] [blame^] | 65 | hidl_vec<AudioPortConfig>* configs); |
Mikhail Naganov | 1b444a5 | 2020-10-29 13:08:05 -0700 | [diff] [blame] | 66 | static status_t audioPortConfigsToHal(const hidl_vec<AudioPortConfig>& configs, |
Mikhail Naganov | b52e93f | 2020-12-10 16:10:08 -0800 | [diff] [blame^] | 67 | std::unique_ptr<audio_port_config[]>* halConfigs); |
| 68 | static status_t audioPortFromHal(const struct audio_port& halPort, AudioPort* port); |
| 69 | static status_t audioPortToHal(const AudioPort& port, struct audio_port* halPort); |
| 70 | static status_t audioSourceFromHal(audio_source_t halSource, AudioSource* source); |
| 71 | static status_t audioSourceToHal(const AudioSource& source, audio_source_t* halSource); |
| 72 | #if MAJOR_VERSION >= 5 |
| 73 | static status_t deviceAddressToHal(const DeviceAddress& device, audio_devices_t* halDeviceType, |
| 74 | char* halDeviceAddress); |
| 75 | static status_t deviceAddressFromHal(audio_devices_t halDeviceType, |
| 76 | const char* halDeviceAddress, DeviceAddress* device); |
| 77 | #endif |
Mikhail Naganov | 1b444a5 | 2020-10-29 13:08:05 -0700 | [diff] [blame] | 78 | |
Mikhail Naganov | b52e93f | 2020-12-10 16:10:08 -0800 | [diff] [blame^] | 79 | #if MAJOR_VERSION <= 6 |
| 80 | // Temporary versions for compatibility with forks of the default implementation. |
| 81 | // Will be removed, do not use! |
| 82 | static status_t audioConfigFromHal(const audio_config_t& halConfig, AudioConfig* config) { |
| 83 | return audioConfigFromHal(halConfig, false /*isInput--ignored*/, config); |
| 84 | } |
Mikhail Naganov | 6e81e9b | 2016-11-16 16:30:17 -0800 | [diff] [blame] | 85 | static std::unique_ptr<audio_port_config[]> audioPortConfigsToHal( |
Mikhail Naganov | 1b444a5 | 2020-10-29 13:08:05 -0700 | [diff] [blame] | 86 | const hidl_vec<AudioPortConfig>& configs) { |
| 87 | std::unique_ptr<audio_port_config[]> halConfigs; |
| 88 | (void)audioPortConfigsToHal(configs, &halConfigs); |
| 89 | return halConfigs; |
| 90 | } |
Mikhail Naganov | b52e93f | 2020-12-10 16:10:08 -0800 | [diff] [blame^] | 91 | #else // V7 and above |
Mikhail Naganov | 1b444a5 | 2020-10-29 13:08:05 -0700 | [diff] [blame] | 92 | static status_t audioChannelMaskFromHal(audio_channel_mask_t halChannelMask, bool isInput, |
| 93 | AudioChannelMask* channelMask); |
Mikhail Naganov | b52e93f | 2020-12-10 16:10:08 -0800 | [diff] [blame^] | 94 | static status_t audioChannelMasksFromHal(const std::vector<std::string>& halChannelMasks, |
| 95 | hidl_vec<AudioChannelMask>* channelMasks); |
Mikhail Naganov | 1b444a5 | 2020-10-29 13:08:05 -0700 | [diff] [blame] | 96 | static status_t audioChannelMaskToHal(const AudioChannelMask& channelMask, |
| 97 | audio_channel_mask_t* halChannelMask); |
| 98 | static status_t audioConfigBaseFromHal(const audio_config_base_t& halConfigBase, bool isInput, |
| 99 | AudioConfigBase* configBase); |
| 100 | static status_t audioConfigBaseToHal(const AudioConfigBase& configBase, |
| 101 | audio_config_base_t* halConfigBase); |
| 102 | static status_t audioDeviceTypeFromHal(audio_devices_t halDevice, AudioDevice* device); |
| 103 | static status_t audioDeviceTypeToHal(const AudioDevice& device, audio_devices_t* halDevice); |
| 104 | static status_t audioFormatFromHal(audio_format_t halFormat, AudioFormat* format); |
Mikhail Naganov | b52e93f | 2020-12-10 16:10:08 -0800 | [diff] [blame^] | 105 | static status_t audioFormatsFromHal(const std::vector<std::string>& halFormats, |
| 106 | hidl_vec<AudioFormat>* formats); |
Mikhail Naganov | 1b444a5 | 2020-10-29 13:08:05 -0700 | [diff] [blame] | 107 | static status_t audioFormatToHal(const AudioFormat& format, audio_format_t* halFormat); |
| 108 | static status_t audioGainModeMaskFromHal(audio_gain_mode_t halGainModeMask, |
| 109 | hidl_vec<AudioGainMode>* gainModeMask); |
| 110 | static status_t audioGainModeMaskToHal(const hidl_vec<AudioGainMode>& gainModeMask, |
| 111 | audio_gain_mode_t* halGainModeMask); |
| 112 | static status_t audioPortFromHal(const struct audio_port_v7& halPort, AudioPort* port); |
| 113 | static status_t audioPortToHal(const AudioPort& port, struct audio_port_v7* halPort); |
| 114 | static status_t audioProfileFromHal(const struct audio_profile& halProfile, bool isInput, |
| 115 | AudioProfile* profile); |
| 116 | static status_t audioProfileToHal(const AudioProfile& profile, |
| 117 | struct audio_profile* halProfile); |
Mikhail Naganov | 1b444a5 | 2020-10-29 13:08:05 -0700 | [diff] [blame] | 118 | static status_t audioStreamTypeFromHal(audio_stream_type_t halStreamType, |
| 119 | AudioStreamType* streamType); |
| 120 | static status_t audioStreamTypeToHal(const AudioStreamType& streamType, |
| 121 | audio_stream_type_t* halStreamType); |
Mikhail Naganov | 1b444a5 | 2020-10-29 13:08:05 -0700 | [diff] [blame] | 122 | |
| 123 | private: |
| 124 | static status_t audioIndexChannelMaskFromHal(audio_channel_mask_t halChannelMask, |
| 125 | AudioChannelMask* channelMask); |
| 126 | static status_t audioInputChannelMaskFromHal(audio_channel_mask_t halChannelMask, |
| 127 | AudioChannelMask* channelMask); |
| 128 | static status_t audioOutputChannelMaskFromHal(audio_channel_mask_t halChannelMask, |
| 129 | AudioChannelMask* channelMask); |
| 130 | static status_t audioPortExtendedInfoFromHal( |
| 131 | audio_port_role_t role, audio_port_type_t type, |
| 132 | const struct audio_port_config_device_ext& device, |
| 133 | const struct audio_port_config_mix_ext& mix, |
| 134 | const struct audio_port_config_session_ext& session, AudioPortExtendedInfo* ext, |
| 135 | bool* isInput); |
| 136 | static status_t audioPortExtendedInfoToHal(const AudioPortExtendedInfo& ext, |
| 137 | audio_port_role_t* role, audio_port_type_t* type, |
| 138 | struct audio_port_config_device_ext* device, |
| 139 | struct audio_port_config_mix_ext* mix, |
| 140 | struct audio_port_config_session_ext* session); |
| 141 | #endif |
Mikhail Naganov | b52e93f | 2020-12-10 16:10:08 -0800 | [diff] [blame^] | 142 | |
| 143 | // V4 and below have DeviceAddress defined in the 'core' interface. |
| 144 | // To avoid duplicating code, the implementations of deviceAddressTo/FromHal |
| 145 | // are defined as templates. These templates can be only used directly by V4 |
| 146 | // and below. |
| 147 | #if MAJOR_VERSION >= 5 |
| 148 | private: |
| 149 | #endif |
| 150 | template <typename DA> |
| 151 | static status_t deviceAddressToHalImpl(const DA& device, audio_devices_t* halDeviceType, |
| 152 | char* halDeviceAddress); |
| 153 | template <typename DA> |
| 154 | static status_t deviceAddressFromHalImpl(audio_devices_t halDeviceType, |
| 155 | const char* halDeviceAddress, DA* device); |
Mikhail Naganov | 6e81e9b | 2016-11-16 16:30:17 -0800 | [diff] [blame] | 156 | }; |
| 157 | |
Mikhail Naganov | b52e93f | 2020-12-10 16:10:08 -0800 | [diff] [blame^] | 158 | #if MAJOR_VERSION <= 6 |
| 159 | #if MAJOR_VERSION >= 4 |
| 160 | inline status_t HidlUtils::audioContentTypeFromHal(const audio_content_type_t halContentType, |
| 161 | AudioContentType* contentType) { |
| 162 | *contentType = AudioContentType(halContentType); |
| 163 | return NO_ERROR; |
| 164 | } |
| 165 | |
| 166 | inline status_t HidlUtils::audioContentTypeToHal(const AudioContentType& contentType, |
| 167 | audio_content_type_t* halContentType) { |
| 168 | *halContentType = static_cast<audio_content_type_t>(contentType); |
| 169 | return NO_ERROR; |
| 170 | } |
| 171 | #endif |
| 172 | |
| 173 | inline status_t HidlUtils::audioSourceFromHal(audio_source_t halSource, AudioSource* source) { |
| 174 | *source = AudioSource(halSource); |
| 175 | return NO_ERROR; |
| 176 | } |
| 177 | |
| 178 | inline status_t HidlUtils::audioSourceToHal(const AudioSource& source, audio_source_t* halSource) { |
| 179 | *halSource = static_cast<audio_source_t>(source); |
| 180 | return NO_ERROR; |
| 181 | } |
| 182 | |
| 183 | template <typename DA> |
| 184 | status_t HidlUtils::deviceAddressToHalImpl(const DA& device, audio_devices_t* halDeviceType, |
| 185 | char* halDeviceAddress) { |
| 186 | *halDeviceType = static_cast<audio_devices_t>(device.device); |
| 187 | memset(halDeviceAddress, 0, AUDIO_DEVICE_MAX_ADDRESS_LEN); |
| 188 | if (audio_is_a2dp_out_device(*halDeviceType) || audio_is_a2dp_in_device(*halDeviceType)) { |
| 189 | snprintf(halDeviceAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN, "%02X:%02X:%02X:%02X:%02X:%02X", |
| 190 | device.address.mac[0], device.address.mac[1], device.address.mac[2], |
| 191 | device.address.mac[3], device.address.mac[4], device.address.mac[5]); |
| 192 | } else if (*halDeviceType == AUDIO_DEVICE_OUT_IP || *halDeviceType == AUDIO_DEVICE_IN_IP) { |
| 193 | snprintf(halDeviceAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN, "%d.%d.%d.%d", |
| 194 | device.address.ipv4[0], device.address.ipv4[1], device.address.ipv4[2], |
| 195 | device.address.ipv4[3]); |
| 196 | } else if (audio_is_usb_out_device(*halDeviceType) || audio_is_usb_in_device(*halDeviceType)) { |
| 197 | snprintf(halDeviceAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN, "card=%d;device=%d", |
| 198 | device.address.alsa.card, device.address.alsa.device); |
| 199 | } else if (*halDeviceType == AUDIO_DEVICE_OUT_BUS || *halDeviceType == AUDIO_DEVICE_IN_BUS) { |
| 200 | snprintf(halDeviceAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN, "%s", device.busAddress.c_str()); |
| 201 | } else if (*halDeviceType == AUDIO_DEVICE_OUT_REMOTE_SUBMIX || |
| 202 | *halDeviceType == AUDIO_DEVICE_IN_REMOTE_SUBMIX) { |
| 203 | snprintf(halDeviceAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN, "%s", |
| 204 | device.rSubmixAddress.c_str()); |
| 205 | } |
| 206 | return NO_ERROR; |
| 207 | } |
| 208 | |
| 209 | template <typename DA> |
| 210 | status_t HidlUtils::deviceAddressFromHalImpl(audio_devices_t halDeviceType, |
| 211 | const char* halDeviceAddress, DA* device) { |
| 212 | if (device == nullptr) { |
| 213 | return BAD_VALUE; |
| 214 | } |
| 215 | device->device = AudioDevice(halDeviceType); |
| 216 | if (halDeviceAddress == nullptr || |
| 217 | strnlen(halDeviceAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0) { |
| 218 | return NO_ERROR; |
| 219 | } |
| 220 | |
| 221 | if (audio_is_a2dp_out_device(halDeviceType) || audio_is_a2dp_in_device(halDeviceType)) { |
| 222 | int status = |
| 223 | sscanf(halDeviceAddress, "%hhX:%hhX:%hhX:%hhX:%hhX:%hhX", &device->address.mac[0], |
| 224 | &device->address.mac[1], &device->address.mac[2], &device->address.mac[3], |
| 225 | &device->address.mac[4], &device->address.mac[5]); |
| 226 | return status == 6 ? OK : BAD_VALUE; |
| 227 | } else if (halDeviceType == AUDIO_DEVICE_OUT_IP || halDeviceType == AUDIO_DEVICE_IN_IP) { |
| 228 | int status = sscanf(halDeviceAddress, "%hhu.%hhu.%hhu.%hhu", &device->address.ipv4[0], |
| 229 | &device->address.ipv4[1], &device->address.ipv4[2], |
| 230 | &device->address.ipv4[3]); |
| 231 | return status == 4 ? OK : BAD_VALUE; |
| 232 | } else if (audio_is_usb_out_device(halDeviceType) || audio_is_usb_in_device(halDeviceType)) { |
| 233 | int status = sscanf(halDeviceAddress, "card=%d;device=%d", &device->address.alsa.card, |
| 234 | &device->address.alsa.device); |
| 235 | return status == 2 ? OK : BAD_VALUE; |
| 236 | } else if (halDeviceType == AUDIO_DEVICE_OUT_BUS || halDeviceType == AUDIO_DEVICE_IN_BUS) { |
| 237 | device->busAddress = halDeviceAddress; |
| 238 | return OK; |
| 239 | } else if (halDeviceType == AUDIO_DEVICE_OUT_REMOTE_SUBMIX || |
| 240 | halDeviceType == AUDIO_DEVICE_IN_REMOTE_SUBMIX) { |
| 241 | device->rSubmixAddress = halDeviceAddress; |
| 242 | return OK; |
| 243 | } |
| 244 | device->busAddress = halDeviceAddress; |
| 245 | return NO_ERROR; |
| 246 | } |
| 247 | #endif // MAJOR_VERSION <= 6 |
| 248 | |
Mikhail Naganov | 543bf9c | 2018-12-11 16:36:53 -0800 | [diff] [blame] | 249 | } // namespace implementation |
Kevin Rocard | 96d2cd9 | 2018-11-14 16:22:07 -0800 | [diff] [blame] | 250 | } // namespace CPP_VERSION |
Kevin Rocard | 6891d7e | 2017-12-14 18:39:39 -0800 | [diff] [blame] | 251 | } // namespace common |
| 252 | } // namespace audio |
| 253 | } // namespace hardware |
Mikhail Naganov | 6e81e9b | 2016-11-16 16:30:17 -0800 | [diff] [blame] | 254 | } // namespace android |
Kevin Rocard | 96d2cd9 | 2018-11-14 16:22:07 -0800 | [diff] [blame] | 255 | |
| 256 | #endif // android_hardware_audio_Hidl_Utils_H_ |