diff --git a/audio/7.0/IDevice.hal b/audio/7.0/IDevice.hal index eecd92ed7c..e30e5456bc 100644 --- a/audio/7.0/IDevice.hal +++ b/audio/7.0/IDevice.hal @@ -117,7 +117,7 @@ interface IDevice { AudioIoHandle ioHandle, DeviceAddress device, AudioConfig config, - bitfield flags, + vec flags, SourceMetadata sourceMetadata) generates ( Result retval, IStreamOut outStream, @@ -142,7 +142,7 @@ interface IDevice { AudioIoHandle ioHandle, DeviceAddress device, AudioConfig config, - bitfield flags, + vec flags, SinkMetadata sinkMetadata) generates ( Result retval, IStreamIn inStream, diff --git a/audio/7.0/IStream.hal b/audio/7.0/IStream.hal index 789cb1dfd1..4fe8218b28 100644 --- a/audio/7.0/IStream.hal +++ b/audio/7.0/IStream.hal @@ -44,49 +44,23 @@ interface IStream { getBufferSize() generates (uint64_t bufferSize); /** - * Return supported native sampling rates of the stream for a given format. - * A supported native sample rate is a sample rate that can be efficiently - * played by the hardware (typically without sample-rate conversions). + * Return supported audio profiles for this particular stream. This method + * is normally called for streams opened on devices that use dynamic + * profiles, e.g. HDMI and USB interfaces. Please note that supported + * profiles of the stream may differ from the capabilities of the connected + * physical device. * - * This function is only called for dynamic profile. If called for - * non-dynamic profile is should return NOT_SUPPORTED or the same list - * as in audio_policy_configuration.xml. - * - * Calling this method is equivalent to getting - * AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES on the legacy HAL. - * - * - * @param format audio format for which the sample rates are supported. - * @return retval operation completion status. - * Must be OK if the format is supported. - * @return sampleRateHz supported sample rates. - */ - getSupportedSampleRates(AudioFormat format) - generates (Result retval, vec sampleRates); - - /** - * Return supported channel masks of the stream. Calling this method is - * equivalent to getting AUDIO_PARAMETER_STREAM_SUP_CHANNELS on the legacy - * HAL. - * - * @param format audio format for which the channel masks are supported. - * @return retval operation completion status. - * Must be OK if the format is supported. - * @return masks supported audio masks. - */ - getSupportedChannelMasks(AudioFormat format) - generates (Result retval, vec> masks); - - /** - * Return supported audio formats of the stream. Calling this method is - * equivalent to getting AUDIO_PARAMETER_STREAM_SUP_FORMATS on the legacy - * HAL. + * For devices with fixed configurations, e.g. built-in audio devices, all + * the profiles are specified in the audio_policy_configuration.xml + * file. For such devices, this method must return the configuration from + * the config file, or NOT_SUPPORTED retval. * * @return retval operation completion status. - * @return formats supported audio formats. + * @return formats supported audio profiles. * Must be non empty if retval is OK. */ - getSupportedFormats() generates (Result retval, vec formats); + getSupportedProfiles() + generates (Result retval, vec profiles); /** * Retrieves basic stream configuration: sample rate, audio format, @@ -94,18 +68,18 @@ interface IStream { * * @return config basic stream configuration. */ - getAudioProperties() generates (AudioBasicConfig config); + getAudioProperties() generates (AudioConfigBase config); /** * Sets stream parameters. Only sets parameters that are specified. - * See the description of AudioBasicConfig for the details. + * See the description of AudioConfigBase for the details. * * Optional method. If implemented, only called on a stopped stream. * * @param config basic stream configuration. * @return retval operation completion status. */ - setAudioProperties(AudioBasicConfig config) generates (Result retval); + setAudioProperties(AudioConfigBase config) generates (Result retval); /** * Applies audio effect to the stream. diff --git a/audio/7.0/config/api/current.txt b/audio/7.0/config/api/current.txt index fd9a8ef200..ac8dc8ae0c 100644 --- a/audio/7.0/config/api/current.txt +++ b/audio/7.0/config/api/current.txt @@ -228,6 +228,33 @@ package audio.policy.configuration.V7_0 { enum_constant public static final audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_WMA_PRO; } + public enum AudioInOutFlag { + method public String getRawName(); + enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_DIRECT; + enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_FAST; + enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_HW_AV_SYNC; + enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_HW_HOTWORD; + enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_MMAP_NOIRQ; + enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_RAW; + enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_SYNC; + enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_INPUT_FLAG_VOIP_TX; + enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD; + enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_DEEP_BUFFER; + enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_DIRECT; + enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_DIRECT_PCM; + enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_FAST; + enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_HW_AV_SYNC; + enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO; + enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_INCALL_MUSIC; + enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_MMAP_NOIRQ; + enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_NON_BLOCKING; + enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_PRIMARY; + enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_RAW; + enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_SYNC; + enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_TTS; + enum_constant public static final audio.policy.configuration.V7_0.AudioInOutFlag AUDIO_OUTPUT_FLAG_VOIP_RX; + } + public class AudioPolicyConfiguration { ctor public AudioPolicyConfiguration(); method public audio.policy.configuration.V7_0.GlobalConfiguration getGlobalConfiguration(); @@ -396,7 +423,7 @@ package audio.policy.configuration.V7_0 { public static class MixPorts.MixPort { ctor public MixPorts.MixPort(); - method public String getFlags(); + method public java.util.List getFlags(); method public audio.policy.configuration.V7_0.Gains getGains(); method public long getMaxActiveCount(); method public long getMaxOpenCount(); @@ -404,7 +431,7 @@ package audio.policy.configuration.V7_0 { method public java.util.List getPreferredUsage(); method public java.util.List getProfile(); method public audio.policy.configuration.V7_0.Role getRole(); - method public void setFlags(String); + method public void setFlags(java.util.List); method public void setGains(audio.policy.configuration.V7_0.Gains); method public void setMaxActiveCount(long); method public void setMaxOpenCount(long); diff --git a/audio/7.0/config/audio_policy_configuration.xsd b/audio/7.0/config/audio_policy_configuration.xsd index 4555a88034..20fe02002e 100644 --- a/audio/7.0/config/audio_policy_configuration.xsd +++ b/audio/7.0/config/audio_policy_configuration.xsd @@ -155,16 +155,41 @@ - + - "|" separated list of audio_output_flags_t or audio_input_flags_t. + The flags indicate suggested stream attributes supported by the profile. - + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/audio/7.0/config/update_audio_policy_config.sh b/audio/7.0/config/update_audio_policy_config.sh index 8714b5f2d3..051a0df916 100755 --- a/audio/7.0/config/update_audio_policy_config.sh +++ b/audio/7.0/config/update_audio_policy_config.sh @@ -128,6 +128,7 @@ updateFile() { for F in $SOURCE_FILES; do updateFile ${F} "channelMasks" "," updateFile ${F} "samplingRates" "," + updateFile ${F} "flags" "|" done; updateIncludes() { diff --git a/audio/7.0/types.hal b/audio/7.0/types.hal index 15ca4921b0..4a9e28915a 100644 --- a/audio/7.0/types.hal +++ b/audio/7.0/types.hal @@ -357,56 +357,15 @@ struct PlaybackRate { }; /** - * The audio output flags serve two purposes: + * The audio flags serve two purposes: * - * - when an output stream is created they indicate its attributes; + * - when a stream is created they indicate its attributes; * - * - when present in an output profile descriptor listed for a particular audio - * hardware module, they indicate that an output stream can be opened that + * - when present in a profile descriptor listed for a particular audio + * hardware module, they indicate that a stream can be opened that * supports the attributes indicated by the flags. + * + * See 'audioIoFlag' in audio_policy_configuration.xsd for the + * list of allowed values. */ -@export(name="audio_output_flags_t", value_prefix="AUDIO_OUTPUT_FLAG_") -enum AudioOutputFlag : int32_t { - NONE = 0x0, // no attributes - DIRECT = 0x1, // this output directly connects a track - // to one output stream: no software mixer - PRIMARY = 0x2, // this output is the primary output of the device. It is - // unique and must be present. It is opened by default and - // receives routing, audio mode and volume controls related - // to voice calls. - FAST = 0x4, // output supports "fast tracks", defined elsewhere - DEEP_BUFFER = 0x8, // use deep audio buffers - COMPRESS_OFFLOAD = 0x10, // offload playback of compressed streams to - // hardware codec - NON_BLOCKING = 0x20, // use non-blocking write - HW_AV_SYNC = 0x40, // output uses a hardware A/V sync - TTS = 0x80, // output for streams transmitted through speaker at a - // sample rate high enough to accommodate lower-range - // ultrasonic p/b - RAW = 0x100, // minimize signal processing - SYNC = 0x200, // synchronize I/O streams - IEC958_NONAUDIO = 0x400, // Audio stream contains compressed audio in SPDIF - // data bursts, not PCM. - DIRECT_PCM = 0x2000, // Audio stream containing PCM data that needs - // to pass through compress path for DSP post proc. - MMAP_NOIRQ = 0x4000, // output operates in MMAP no IRQ mode. - VOIP_RX = 0x8000, // preferred output for VoIP calls. - /** preferred output for call music */ - INCALL_MUSIC = 0x10000, -}; - -/** - * The audio input flags are analogous to audio output flags. - */ -@export(name="audio_input_flags_t", value_prefix="AUDIO_INPUT_FLAG_") -enum AudioInputFlag : int32_t { - NONE = 0x0, // no attributes - FAST = 0x1, // prefer an input that supports "fast tracks" - HW_HOTWORD = 0x2, // prefer an input that captures from hw hotword source - RAW = 0x4, // minimize signal processing - SYNC = 0x8, // synchronize I/O streams - MMAP_NOIRQ = 0x10, // input operates in MMAP no IRQ mode. - VOIP_TX = 0x20, // preferred input for VoIP calls. - HW_AV_SYNC = 0x40, // input connected to an output that uses a hardware A/V sync - DIRECT = 0x80, // for acquiring encoded streams -}; +typedef string AudioInOutFlag; diff --git a/audio/README b/audio/README deleted file mode 100644 index afafbe32d2..0000000000 --- a/audio/README +++ /dev/null @@ -1,36 +0,0 @@ -Directory structure of the audio HIDL related code. - -Run `common/all-versions/copyHAL.sh` to create a new version of the audio HAL -based on an existing one. - -audio -|-- 2.0 <== core 2.0 HIDL API. .hal can not be moved into the core directory -| because that would change its namespace and include path -|-- 4.0 <== Version 4.0 of the core API -| -|-- ... -| -|-- common <== code common to audio core and effect API -| |-- 2.0 <== HIDL API of V2 -| |-- 4.0 -| |-- ... -| `-- all-versions <== code common to all version of both core and effect API -| |-- default <== implementation shared code between core and effect impl -| |-- test <== utilities used by tests -| `-- util <== utilities used by both implementation and tests -| -|-- core <== VTS and default implementation of the core API (not HIDL, see /audio/2.0)) -| `-- all-versions <== Code is version independent through #if and separate files -| |-- default <== code that wraps the legacy API -| `-- vts <== vts of core API -| |-- 2.0 <== 2.0 specific tests and helpers -| |-- 4.0 -| |-- ... -| -`-- effect <== idem for the effect API - |-- 2.0 - |-- 4.0 - |-- ... - `-- all-versions - |-- default - `-- vts diff --git a/audio/README.md b/audio/README.md new file mode 100644 index 0000000000..b77b9ba42d --- /dev/null +++ b/audio/README.md @@ -0,0 +1,53 @@ +# Audio HAL + +Directory structure of the audio HAL related code. + +Run `common/all-versions/copyHAL.sh` to create a new version of the audio HAL +based on an existing one. + +## Directory Structure + +* `2.0` -- version 2.0 of the core HIDL API. Note that `.hal` files + can not be moved into the `core` directory because that would change + its namespace and include path. + - `config` -- the XSD schema for the Audio Policy Manager + configuration file. +* `4.0` -- version 4.0 of the core HIDL API. +* ... +* `common` -- common types for audio core and effect HIDL API. + - `2.0` -- version 2.0 of the common types HIDL API. + - `4.0` -- version 4.0. + - ... + - `7.0` -- version 7.0. + - `example` -- example implementation of the core and effect + V7.0 API. It represents a "fake" audio HAL that doesn't + actually communicate with hardware. + - `all-versions` -- code common to all version of both core and effect API. + - `default` -- shared code of the default implementation. + - `service` -- vendor HAL service for hosting the default + implementation. + - `test` -- utilities used by tests. + - `util` -- utilities used by both implementation and tests. +* `core` -- VTS tests and the default implementation of the core API + (not HIDL API, it's in `audio/N.M`). + - `7.0` -- code specific to version V7.0 of the core HIDL API + - `all-versions` -- the code is common between all versions, + version-specific parts are enclosed into conditional directives + of preprocessor or reside in dedicated files. + - `default` -- code that wraps the legacy API (from + `hardware/libhardware`). + - `vts` VTS tests for the core HIDL API. +* `effect` -- same for the effect HIDL API. + - `2.0` + - `config` -- the XSD schema for the Audio Effects configuration + file. + - `4.0` + - ... + - `all-versions` + - `default` + - `vts` +* `policy` -- Configurable Audio Policy schemes. + - `1.0` -- note that versions of CAP are not linked to the versions + of audio HAL. + - `vts` -- VTS tests for validating actual configuration files. + - `xml` -- XSD schemas for CAP configuration files. diff --git a/audio/common/7.0/Android.bp b/audio/common/7.0/Android.bp index e24871c8b5..1c016b401b 100644 --- a/audio/common/7.0/Android.bp +++ b/audio/common/7.0/Android.bp @@ -16,9 +16,12 @@ hidl_interface { cc_library { name: "android.hardware.audio.common@7.0-enums", vendor_available: true, - generated_sources: ["audio_policy_configuration_V7_0"], generated_headers: ["audio_policy_configuration_V7_0"], + generated_sources: ["audio_policy_configuration_V7_0"], header_libs: ["libxsdc-utils"], + export_generated_headers: ["audio_policy_configuration_V7_0"], + export_header_lib_headers: ["libxsdc-utils"], + export_include_dirs: ["enums/include"], shared_libs: [ "libbase", "liblog", diff --git a/audio/common/7.0/enums/include/audio_policy_configuration_V7_0-enums.h b/audio/common/7.0/enums/include/audio_policy_configuration_V7_0-enums.h new file mode 100644 index 0000000000..d5fedce100 --- /dev/null +++ b/audio/common/7.0/enums/include/audio_policy_configuration_V7_0-enums.h @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2020 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 AUDIO_POLICY_CONFIGURATION_V7_0_ENUMS_H +#define AUDIO_POLICY_CONFIGURATION_V7_0_ENUMS_H + +#include + +#include + +namespace audio::policy::configuration::V7_0 { + +static inline size_t getChannelCount(AudioChannelMask mask) { + switch (mask) { + case AudioChannelMask::AUDIO_CHANNEL_OUT_MONO: + case AudioChannelMask::AUDIO_CHANNEL_IN_MONO: + case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_1: + return 1; + case AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO: + case AudioChannelMask::AUDIO_CHANNEL_OUT_MONO_HAPTIC_A: + case AudioChannelMask::AUDIO_CHANNEL_OUT_HAPTIC_AB: + case AudioChannelMask::AUDIO_CHANNEL_IN_STEREO: + case AudioChannelMask::AUDIO_CHANNEL_IN_FRONT_BACK: + case AudioChannelMask::AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO: + case AudioChannelMask::AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO: + case AudioChannelMask::AUDIO_CHANNEL_IN_VOICE_CALL_MONO: + case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_2: + return 2; + case AudioChannelMask::AUDIO_CHANNEL_OUT_2POINT1: + case AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO_HAPTIC_A: + case AudioChannelMask::AUDIO_CHANNEL_OUT_MONO_HAPTIC_AB: + case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_3: + return 3; + case AudioChannelMask::AUDIO_CHANNEL_OUT_2POINT0POINT2: + case AudioChannelMask::AUDIO_CHANNEL_OUT_QUAD: + case AudioChannelMask::AUDIO_CHANNEL_OUT_QUAD_BACK: + case AudioChannelMask::AUDIO_CHANNEL_OUT_QUAD_SIDE: + case AudioChannelMask::AUDIO_CHANNEL_OUT_SURROUND: + case AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO_HAPTIC_AB: + case AudioChannelMask::AUDIO_CHANNEL_IN_2POINT0POINT2: + case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_4: + return 4; + case AudioChannelMask::AUDIO_CHANNEL_OUT_2POINT1POINT2: + case AudioChannelMask::AUDIO_CHANNEL_OUT_3POINT0POINT2: + case AudioChannelMask::AUDIO_CHANNEL_OUT_PENTA: + case AudioChannelMask::AUDIO_CHANNEL_IN_2POINT1POINT2: + case AudioChannelMask::AUDIO_CHANNEL_IN_3POINT0POINT2: + case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_5: + return 5; + case AudioChannelMask::AUDIO_CHANNEL_OUT_3POINT1POINT2: + case AudioChannelMask::AUDIO_CHANNEL_OUT_5POINT1: + case AudioChannelMask::AUDIO_CHANNEL_OUT_5POINT1_BACK: + case AudioChannelMask::AUDIO_CHANNEL_OUT_5POINT1_SIDE: + case AudioChannelMask::AUDIO_CHANNEL_IN_6: + case AudioChannelMask::AUDIO_CHANNEL_IN_3POINT1POINT2: + case AudioChannelMask::AUDIO_CHANNEL_IN_5POINT1: + case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_6: + return 6; + case AudioChannelMask::AUDIO_CHANNEL_OUT_6POINT1: + case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_7: + return 7; + case AudioChannelMask::AUDIO_CHANNEL_OUT_5POINT1POINT2: + case AudioChannelMask::AUDIO_CHANNEL_OUT_7POINT1: + case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_8: + return 8; + case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_9: + return 9; + case AudioChannelMask::AUDIO_CHANNEL_OUT_5POINT1POINT4: + case AudioChannelMask::AUDIO_CHANNEL_OUT_7POINT1POINT2: + case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_10: + return 10; + case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_11: + return 11; + case AudioChannelMask::AUDIO_CHANNEL_OUT_7POINT1POINT4: + case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_12: + return 12; + case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_13: + return 13; + case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_14: + return 14; + case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_15: + return 15; + case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_16: + return 16; + case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_17: + return 17; + case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_18: + return 18; + case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_19: + return 19; + case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_20: + return 20; + case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_21: + return 21; + case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_22: + return 22; + case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_23: + return 23; + case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_24: + return 24; + case AudioChannelMask::UNKNOWN: + return 0; + // No default to make sure all cases are covered. + } + // This is to avoid undefined behavior if 'mask' isn't a valid enum value. + return 0; +} + +static inline ssize_t getChannelCount(const std::string& mask) { + return getChannelCount(stringToAudioChannelMask(mask)); +} + +static inline bool isOutputDevice(AudioDevice device) { + switch (device) { + case AudioDevice::UNKNOWN: + case AudioDevice::AUDIO_DEVICE_NONE: + return false; + case AudioDevice::AUDIO_DEVICE_OUT_EARPIECE: + case AudioDevice::AUDIO_DEVICE_OUT_SPEAKER: + case AudioDevice::AUDIO_DEVICE_OUT_WIRED_HEADSET: + case AudioDevice::AUDIO_DEVICE_OUT_WIRED_HEADPHONE: + case AudioDevice::AUDIO_DEVICE_OUT_BLUETOOTH_SCO: + case AudioDevice::AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET: + case AudioDevice::AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT: + case AudioDevice::AUDIO_DEVICE_OUT_BLUETOOTH_A2DP: + case AudioDevice::AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES: + case AudioDevice::AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER: + case AudioDevice::AUDIO_DEVICE_OUT_AUX_DIGITAL: + case AudioDevice::AUDIO_DEVICE_OUT_HDMI: + case AudioDevice::AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET: + case AudioDevice::AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET: + case AudioDevice::AUDIO_DEVICE_OUT_USB_ACCESSORY: + case AudioDevice::AUDIO_DEVICE_OUT_USB_DEVICE: + case AudioDevice::AUDIO_DEVICE_OUT_REMOTE_SUBMIX: + case AudioDevice::AUDIO_DEVICE_OUT_TELEPHONY_TX: + case AudioDevice::AUDIO_DEVICE_OUT_LINE: + case AudioDevice::AUDIO_DEVICE_OUT_HDMI_ARC: + case AudioDevice::AUDIO_DEVICE_OUT_SPDIF: + case AudioDevice::AUDIO_DEVICE_OUT_FM: + case AudioDevice::AUDIO_DEVICE_OUT_AUX_LINE: + case AudioDevice::AUDIO_DEVICE_OUT_SPEAKER_SAFE: + case AudioDevice::AUDIO_DEVICE_OUT_IP: + case AudioDevice::AUDIO_DEVICE_OUT_BUS: + case AudioDevice::AUDIO_DEVICE_OUT_PROXY: + case AudioDevice::AUDIO_DEVICE_OUT_USB_HEADSET: + case AudioDevice::AUDIO_DEVICE_OUT_HEARING_AID: + case AudioDevice::AUDIO_DEVICE_OUT_ECHO_CANCELLER: + case AudioDevice::AUDIO_DEVICE_OUT_DEFAULT: + case AudioDevice::AUDIO_DEVICE_OUT_STUB: + return true; + case AudioDevice::AUDIO_DEVICE_IN_COMMUNICATION: + case AudioDevice::AUDIO_DEVICE_IN_AMBIENT: + case AudioDevice::AUDIO_DEVICE_IN_BUILTIN_MIC: + case AudioDevice::AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET: + case AudioDevice::AUDIO_DEVICE_IN_WIRED_HEADSET: + case AudioDevice::AUDIO_DEVICE_IN_AUX_DIGITAL: + case AudioDevice::AUDIO_DEVICE_IN_HDMI: + case AudioDevice::AUDIO_DEVICE_IN_VOICE_CALL: + case AudioDevice::AUDIO_DEVICE_IN_TELEPHONY_RX: + case AudioDevice::AUDIO_DEVICE_IN_BACK_MIC: + case AudioDevice::AUDIO_DEVICE_IN_REMOTE_SUBMIX: + case AudioDevice::AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET: + case AudioDevice::AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET: + case AudioDevice::AUDIO_DEVICE_IN_USB_ACCESSORY: + case AudioDevice::AUDIO_DEVICE_IN_USB_DEVICE: + case AudioDevice::AUDIO_DEVICE_IN_FM_TUNER: + case AudioDevice::AUDIO_DEVICE_IN_TV_TUNER: + case AudioDevice::AUDIO_DEVICE_IN_LINE: + case AudioDevice::AUDIO_DEVICE_IN_SPDIF: + case AudioDevice::AUDIO_DEVICE_IN_BLUETOOTH_A2DP: + case AudioDevice::AUDIO_DEVICE_IN_LOOPBACK: + case AudioDevice::AUDIO_DEVICE_IN_IP: + case AudioDevice::AUDIO_DEVICE_IN_BUS: + case AudioDevice::AUDIO_DEVICE_IN_PROXY: + case AudioDevice::AUDIO_DEVICE_IN_USB_HEADSET: + case AudioDevice::AUDIO_DEVICE_IN_BLUETOOTH_BLE: + case AudioDevice::AUDIO_DEVICE_IN_HDMI_ARC: + case AudioDevice::AUDIO_DEVICE_IN_ECHO_REFERENCE: + case AudioDevice::AUDIO_DEVICE_IN_DEFAULT: + case AudioDevice::AUDIO_DEVICE_IN_STUB: + return false; + // No default to make sure all cases are covered. + } + // This is to avoid undefined behavior if 'device' isn't a valid enum value. + return false; +} + +static inline bool isOutputDevice(const std::string& device) { + return isOutputDevice(stringToAudioDevice(device)); +} + +} // namespace audio::policy::configuration::V7_0 + +#endif // AUDIO_POLICY_CONFIGURATION_V7_0_ENUMS_H diff --git a/audio/common/7.0/example/Android.bp b/audio/common/7.0/example/Android.bp new file mode 100644 index 0000000000..03c1cd89cd --- /dev/null +++ b/audio/common/7.0/example/Android.bp @@ -0,0 +1,45 @@ +// +// Copyright (C) 2020 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. + +cc_binary { + name: "android.hardware.audio@7.0-service.example", + vendor: true, + relative_install_path: "hw", + init_rc: ["android.hardware.audio@7.0-service.example.rc"], + vintf_fragments: ["android.hardware.audio@7.0-service.example.xml"], + srcs: [ + "DevicesFactory.cpp", + "Effect.cpp", + "EffectsFactory.cpp", + "EqualizerEffect.cpp", + "LoudnessEnhancerEffect.cpp", + "service.cpp", + ], + cflags: [ + "-Wall", + "-Werror", + ], + shared_libs: [ + "libcutils", + "libhidlbase", + "liblog", + "libxml2", + "libutils", + "android.hardware.audio@7.0", + "android.hardware.audio.common@7.0", + "android.hardware.audio.common@7.0-enums", + "android.hardware.audio.effect@7.0", + ], +} diff --git a/audio/common/7.0/example/DevicesFactory.cpp b/audio/common/7.0/example/DevicesFactory.cpp new file mode 100644 index 0000000000..ddd5fef8f7 --- /dev/null +++ b/audio/common/7.0/example/DevicesFactory.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 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. + */ + +#define LOG_TAG "DevicesFactory7.0" +#include + +#include "DevicesFactory.h" + +using ::android::hardware::hidl_string; +using ::android::hardware::Return; +using ::android::hardware::Void; + +namespace android::hardware::audio::V7_0::implementation { + +Return DevicesFactory::openDevice(const hidl_string& device, openDevice_cb _hidl_cb) { + (void)device; + _hidl_cb(Result::INVALID_ARGUMENTS, nullptr); + return Void(); +} + +Return DevicesFactory::openPrimaryDevice(openPrimaryDevice_cb _hidl_cb) { + _hidl_cb(Result::INVALID_ARGUMENTS, nullptr); + return Void(); +} + +} // namespace android::hardware::audio::V7_0::implementation diff --git a/audio/common/7.0/example/DevicesFactory.h b/audio/common/7.0/example/DevicesFactory.h new file mode 100644 index 0000000000..00f665c17e --- /dev/null +++ b/audio/common/7.0/example/DevicesFactory.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2020 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. + */ + +#pragma once + +#include + +namespace android::hardware::audio::V7_0::implementation { + +class DevicesFactory : public IDevicesFactory { + public: + DevicesFactory() = default; + + ::android::hardware::Return openDevice(const ::android::hardware::hidl_string& device, + openDevice_cb _hidl_cb) override; + + ::android::hardware::Return openPrimaryDevice(openPrimaryDevice_cb _hidl_cb) override; +}; + +} // namespace android::hardware::audio::V7_0::implementation diff --git a/audio/common/7.0/example/Effect.cpp b/audio/common/7.0/example/Effect.cpp new file mode 100644 index 0000000000..423754d593 --- /dev/null +++ b/audio/common/7.0/example/Effect.cpp @@ -0,0 +1,224 @@ +/* + * Copyright (C) 2020 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. + */ + +#define LOG_TAG "EffectsFactory7.0" +#include + +#include + +#include "Effect.h" + +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; +using namespace ::android::hardware::audio::common::V7_0; +// Make an alias for enumerations generated from the APM config XSD. +namespace xsd { +using namespace ::audio::policy::configuration::V7_0; +} + +namespace android::hardware::audio::effect::V7_0::implementation { + +Return Effect::init() { + return Result::OK; +} + +Return Effect::setConfig( + const EffectConfig& config, + const ::android::sp& inputBufferProvider, + const ::android::sp& outputBufferProvider) { + (void)config; + (void)inputBufferProvider; + (void)outputBufferProvider; + return Result::OK; +} + +Return Effect::reset() { + return Result::OK; +} + +Return Effect::enable() { + if (!mEnabled) { + mEnabled = true; + return Result::OK; + } else { + return Result::NOT_SUPPORTED; + } +} + +Return Effect::disable() { + if (mEnabled) { + mEnabled = false; + return Result::OK; + } else { + return Result::NOT_SUPPORTED; + } +} + +Return Effect::setDevice(const DeviceAddress& device) { + (void)device; + return Result::OK; +} + +Return Effect::setAndGetVolume(const hidl_vec& volumes, + setAndGetVolume_cb _hidl_cb) { + (void)volumes; + _hidl_cb(Result::OK, hidl_vec{}); + return Void(); +} + +Return Effect::volumeChangeNotification(const hidl_vec& volumes) { + (void)volumes; + return Result::OK; +} + +Return Effect::setAudioMode(AudioMode mode) { + (void)mode; + return Result::OK; +} + +Return Effect::setConfigReverse( + const EffectConfig& config, + const ::android::sp& inputBufferProvider, + const ::android::sp& outputBufferProvider) { + (void)config; + (void)inputBufferProvider; + (void)outputBufferProvider; + return Result::OK; +} + +Return Effect::setInputDevice(const DeviceAddress& device) { + (void)device; + return Result::OK; +} + +Return Effect::getConfig(getConfig_cb _hidl_cb) { + const EffectConfig config = {{} /* inputCfg */, + // outputCfg + {{} /* buffer */, + 48000 /* samplingRateHz */, + toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO), + toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT), + EffectBufferAccess::ACCESS_ACCUMULATE, + 0 /* mask */}}; + _hidl_cb(Result::OK, config); + return Void(); +} + +Return Effect::getConfigReverse(getConfigReverse_cb _hidl_cb) { + _hidl_cb(Result::OK, EffectConfig{}); + return Void(); +} + +Return Effect::getSupportedAuxChannelsConfigs(uint32_t maxConfigs, + getSupportedAuxChannelsConfigs_cb _hidl_cb) { + (void)maxConfigs; + _hidl_cb(Result::OK, hidl_vec{}); + return Void(); +} + +Return Effect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) { + _hidl_cb(Result::OK, EffectAuxChannelsConfig{}); + return Void(); +} + +Return Effect::setAuxChannelsConfig(const EffectAuxChannelsConfig& config) { + (void)config; + return Result::OK; +} + +Return Effect::setAudioSource(const hidl_string& source) { + (void)source; + return Result::OK; +} + +Return Effect::offload(const EffectOffloadParameter& param) { + (void)param; + return Result::OK; +} + +Return Effect::getDescriptor(getDescriptor_cb _hidl_cb) { + _hidl_cb(Result::OK, mDescriptor); + return Void(); +} + +Return Effect::prepareForProcessing(prepareForProcessing_cb _hidl_cb) { + _hidl_cb(Result::OK, MQDescriptor{}); + return Void(); +} + +Return Effect::setProcessBuffers(const AudioBuffer& inBuffer, + const AudioBuffer& outBuffer) { + (void)inBuffer; + (void)outBuffer; + return Result::OK; +} + +Return Effect::command(uint32_t commandId, const hidl_vec& data, + uint32_t resultMaxSize, command_cb _hidl_cb) { + (void)commandId; + (void)data; + (void)resultMaxSize; + _hidl_cb(-EINVAL, hidl_vec{}); + return Void(); +} + +Return Effect::setParameter(const hidl_vec& parameter, + const hidl_vec& value) { + (void)parameter; + (void)value; + return Result::OK; +} + +Return Effect::getParameter(const hidl_vec& parameter, uint32_t valueMaxSize, + getParameter_cb _hidl_cb) { + (void)parameter; + (void)valueMaxSize; + _hidl_cb(Result::OK, hidl_vec{}); + return Void(); +} + +Return Effect::getSupportedConfigsForFeature(uint32_t featureId, uint32_t maxConfigs, + uint32_t configSize, + getSupportedConfigsForFeature_cb _hidl_cb) { + (void)featureId; + (void)maxConfigs; + (void)configSize; + _hidl_cb(Result::OK, 0, hidl_vec{}); + return Void(); +} + +Return Effect::getCurrentConfigForFeature(uint32_t featureId, uint32_t configSize, + getCurrentConfigForFeature_cb _hidl_cb) { + (void)featureId; + (void)configSize; + _hidl_cb(Result::OK, hidl_vec{}); + return Void(); +} + +Return Effect::setCurrentConfigForFeature(uint32_t featureId, + const hidl_vec& configData) { + (void)featureId; + (void)configData; + return Result::OK; +} + +Return Effect::close() { + return Result::OK; +} + +} // namespace android::hardware::audio::effect::V7_0::implementation diff --git a/audio/common/7.0/example/Effect.h b/audio/common/7.0/example/Effect.h new file mode 100644 index 0000000000..fa7f41bda6 --- /dev/null +++ b/audio/common/7.0/example/Effect.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2020 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. + */ + +#pragma once + +#include + +namespace android::hardware::audio::effect::V7_0::implementation { + +class Effect : public IEffect { + public: + explicit Effect(const EffectDescriptor& descriptor) : mDescriptor(descriptor) {} + + ::android::hardware::Return init() override; + ::android::hardware::Return setConfig( + const EffectConfig& config, + const ::android::sp& inputBufferProvider, + const ::android::sp& outputBufferProvider) override; + ::android::hardware::Return reset() override; + ::android::hardware::Return enable() override; + ::android::hardware::Return disable() override; + ::android::hardware::Return setDevice( + const ::android::hardware::audio::common::V7_0::DeviceAddress& device) override; + ::android::hardware::Return setAndGetVolume( + const ::android::hardware::hidl_vec& volumes, + setAndGetVolume_cb _hidl_cb) override; + ::android::hardware::Return volumeChangeNotification( + const ::android::hardware::hidl_vec& volumes) override; + ::android::hardware::Return setAudioMode( + ::android::hardware::audio::common::V7_0::AudioMode mode) override; + ::android::hardware::Return setConfigReverse( + const EffectConfig& config, + const ::android::sp& inputBufferProvider, + const ::android::sp& outputBufferProvider) override; + ::android::hardware::Return setInputDevice( + const ::android::hardware::audio::common::V7_0::DeviceAddress& device) override; + ::android::hardware::Return getConfig(getConfig_cb _hidl_cb) override; + ::android::hardware::Return getConfigReverse(getConfigReverse_cb _hidl_cb) override; + ::android::hardware::Return getSupportedAuxChannelsConfigs( + uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) override; + ::android::hardware::Return getAuxChannelsConfig( + getAuxChannelsConfig_cb _hidl_cb) override; + ::android::hardware::Return setAuxChannelsConfig( + const EffectAuxChannelsConfig& config) override; + ::android::hardware::Return setAudioSource( + const ::android::hardware::hidl_string& source) override; + ::android::hardware::Return offload(const EffectOffloadParameter& param) override; + ::android::hardware::Return getDescriptor(getDescriptor_cb _hidl_cb) override; + ::android::hardware::Return prepareForProcessing( + prepareForProcessing_cb _hidl_cb) override; + ::android::hardware::Return setProcessBuffers(const AudioBuffer& inBuffer, + const AudioBuffer& outBuffer) override; + ::android::hardware::Return command(uint32_t commandId, + const ::android::hardware::hidl_vec& data, + uint32_t resultMaxSize, command_cb _hidl_cb) override; + ::android::hardware::Return setParameter( + const ::android::hardware::hidl_vec& parameter, + const ::android::hardware::hidl_vec& value) override; + ::android::hardware::Return getParameter( + const ::android::hardware::hidl_vec& parameter, uint32_t valueMaxSize, + getParameter_cb _hidl_cb) override; + ::android::hardware::Return getSupportedConfigsForFeature( + uint32_t featureId, uint32_t maxConfigs, uint32_t configSize, + getSupportedConfigsForFeature_cb _hidl_cb) override; + ::android::hardware::Return getCurrentConfigForFeature( + uint32_t featureId, uint32_t configSize, + getCurrentConfigForFeature_cb _hidl_cb) override; + ::android::hardware::Return setCurrentConfigForFeature( + uint32_t featureId, const ::android::hardware::hidl_vec& configData) override; + ::android::hardware::Return close() override; + + private: + const EffectDescriptor mDescriptor; + bool mEnabled = false; +}; + +} // namespace android::hardware::audio::effect::V7_0::implementation diff --git a/audio/common/7.0/example/EffectsFactory.cpp b/audio/common/7.0/example/EffectsFactory.cpp new file mode 100644 index 0000000000..7d333ae040 --- /dev/null +++ b/audio/common/7.0/example/EffectsFactory.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2020 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. + */ + +#define LOG_TAG "EffectsFactory7.0" +#include + +#include "EffectsFactory.h" +#include "EqualizerEffect.h" +#include "LoudnessEnhancerEffect.h" + +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; +using namespace ::android::hardware::audio::common::V7_0; + +namespace android::hardware::audio::effect::V7_0::implementation { + +Return EffectsFactory::getAllDescriptors(getAllDescriptors_cb _hidl_cb) { + hidl_vec descriptors; + descriptors.resize(2); + descriptors[0] = EqualizerEffect::getDescriptor(); + descriptors[1] = LoudnessEnhancerEffect::getDescriptor(); + _hidl_cb(Result::OK, descriptors); + return Void(); +} + +Return EffectsFactory::getDescriptor(const Uuid& uuid, getDescriptor_cb _hidl_cb) { + if (auto desc = EqualizerEffect::getDescriptor(); uuid == desc.type || uuid == desc.uuid) { + _hidl_cb(Result::OK, desc); + } else if (auto desc = LoudnessEnhancerEffect::getDescriptor(); + uuid == desc.type || uuid == desc.uuid) { + _hidl_cb(Result::OK, desc); + } else { + _hidl_cb(Result::INVALID_ARGUMENTS, EffectDescriptor{}); + } + return Void(); +} + +Return EffectsFactory::createEffect(const Uuid& uuid, int32_t session, int32_t ioHandle, + int32_t device, createEffect_cb _hidl_cb) { + (void)session; + (void)ioHandle; + (void)device; + if (auto desc = EqualizerEffect::getDescriptor(); uuid == desc.type || uuid == desc.uuid) { + _hidl_cb(Result::OK, new EqualizerEffect(), 0); + } else if (auto desc = LoudnessEnhancerEffect::getDescriptor(); + uuid == desc.type || uuid == desc.uuid) { + _hidl_cb(Result::OK, new LoudnessEnhancerEffect(), 0); + } else { + _hidl_cb(Result::INVALID_ARGUMENTS, nullptr, 0); + } + return Void(); +} + +Return EffectsFactory::debug(const hidl_handle& fd, const hidl_vec& options) { + (void)fd; + (void)options; + return Void(); +} + +} // namespace android::hardware::audio::effect::V7_0::implementation diff --git a/audio/common/7.0/example/EffectsFactory.h b/audio/common/7.0/example/EffectsFactory.h new file mode 100644 index 0000000000..8fec70cb35 --- /dev/null +++ b/audio/common/7.0/example/EffectsFactory.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 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. + */ + +#pragma once + +#include + +namespace android::hardware::audio::effect::V7_0::implementation { + +class EffectsFactory : public IEffectsFactory { + public: + EffectsFactory() = default; + + ::android::hardware::Return getAllDescriptors(getAllDescriptors_cb _hidl_cb) override; + ::android::hardware::Return getDescriptor( + const ::android::hardware::audio::common::V7_0::Uuid& uuid, + getDescriptor_cb _hidl_cb) override; + ::android::hardware::Return createEffect( + const ::android::hardware::audio::common::V7_0::Uuid& uuid, int32_t session, + int32_t ioHandle, int32_t device, createEffect_cb _hidl_cb) override; + ::android::hardware::Return + debug(const ::android::hardware::hidl_handle& fd, + const ::android::hardware::hidl_vec<::android::hardware::hidl_string>& options) override; +}; + +} // namespace android::hardware::audio::effect::V7_0::implementation diff --git a/audio/common/7.0/example/EqualizerEffect.cpp b/audio/common/7.0/example/EqualizerEffect.cpp new file mode 100644 index 0000000000..c93c5a90fb --- /dev/null +++ b/audio/common/7.0/example/EqualizerEffect.cpp @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2020 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. + */ + +#include + +#define LOG_TAG "EffectsFactory7.0" +#include + +#include "EqualizerEffect.h" + +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; +using namespace ::android::hardware::audio::common::V7_0; + +namespace android::hardware::audio::effect::V7_0::implementation { + +const EffectDescriptor& EqualizerEffect::getDescriptor() { + // Note: for VTS tests only 'type' and 'uuid' fields are required. + // The actual implementation must provide meaningful values + // for all fields of the descriptor. + static const EffectDescriptor descriptor = { + .type = + {// Same UUID as AudioEffect.EFFECT_TYPE_EQUALIZER in Java. + 0x0bed4300, 0xddd6, 0x11db, 0x8f34, + std::array{{0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}}, + .uuid = {0, 0, 0, 1, std::array{{0, 0, 0, 0, 0, 0}}}}; + return descriptor; +} + +EqualizerEffect::EqualizerEffect() : mEffect(new Effect(getDescriptor())) { + mProperties.bandLevels.resize(kNumBands); +} + +Return EqualizerEffect::getNumBands(getNumBands_cb _hidl_cb) { + _hidl_cb(Result::OK, kNumBands); + return Void(); +} + +Return EqualizerEffect::getLevelRange(getLevelRange_cb _hidl_cb) { + _hidl_cb(Result::OK, std::numeric_limits::min(), std::numeric_limits::max()); + return Void(); +} + +Return EqualizerEffect::setBandLevel(uint16_t band, int16_t level) { + if (band < kNumBands) { + mProperties.bandLevels[band] = level; + return Result::OK; + } else { + return Result::INVALID_ARGUMENTS; + } +} + +Return EqualizerEffect::getBandLevel(uint16_t band, getBandLevel_cb _hidl_cb) { + if (band < kNumBands) { + _hidl_cb(Result::OK, mProperties.bandLevels[band]); + } else { + _hidl_cb(Result::INVALID_ARGUMENTS, 0); + } + return Void(); +} + +Return EqualizerEffect::getBandCenterFrequency(uint16_t band, + getBandCenterFrequency_cb _hidl_cb) { + (void)band; + _hidl_cb(Result::OK, 0); + return Void(); +} + +Return EqualizerEffect::getBandFrequencyRange(uint16_t band, + getBandFrequencyRange_cb _hidl_cb) { + (void)band; + _hidl_cb(Result::OK, 0, 1); + return Void(); +} + +Return EqualizerEffect::getBandForFrequency(uint32_t freq, getBandForFrequency_cb _hidl_cb) { + (void)freq; + _hidl_cb(Result::OK, 0); + return Void(); +} + +Return EqualizerEffect::getPresetNames(getPresetNames_cb _hidl_cb) { + hidl_vec presetNames; + presetNames.resize(kNumPresets); + presetNames[0] = "default"; + _hidl_cb(Result::OK, presetNames); + return Void(); +} + +Return EqualizerEffect::setCurrentPreset(uint16_t preset) { + if (preset < kNumPresets) { + mProperties.curPreset = preset; + return Result::OK; + } else { + return Result::INVALID_ARGUMENTS; + } +} + +Return EqualizerEffect::getCurrentPreset(getCurrentPreset_cb _hidl_cb) { + _hidl_cb(Result::OK, mProperties.curPreset); + return Void(); +} + +Return EqualizerEffect::setAllProperties( + const IEqualizerEffect::AllProperties& properties) { + mProperties = properties; + return Result::OK; +} + +Return EqualizerEffect::getAllProperties(getAllProperties_cb _hidl_cb) { + _hidl_cb(Result::OK, mProperties); + return Void(); +} + +} // namespace android::hardware::audio::effect::V7_0::implementation diff --git a/audio/common/7.0/example/EqualizerEffect.h b/audio/common/7.0/example/EqualizerEffect.h new file mode 100644 index 0000000000..11853c3392 --- /dev/null +++ b/audio/common/7.0/example/EqualizerEffect.h @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2020 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. + */ + +#pragma once + +#include + +#include "Effect.h" + +namespace android::hardware::audio::effect::V7_0::implementation { + +class EqualizerEffect : public IEqualizerEffect { + public: + static const EffectDescriptor& getDescriptor(); + + EqualizerEffect(); + + // Methods from IEffect interface. + ::android::hardware::Return init() override { return mEffect->init(); } + ::android::hardware::Return setConfig( + const EffectConfig& config, + const ::android::sp& inputBufferProvider, + const ::android::sp& outputBufferProvider) override { + return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider); + } + ::android::hardware::Return reset() override { return mEffect->reset(); } + ::android::hardware::Return enable() override { return mEffect->enable(); } + ::android::hardware::Return disable() override { return mEffect->disable(); } + ::android::hardware::Return setDevice( + const ::android::hardware::audio::common::V7_0::DeviceAddress& device) override { + return mEffect->setDevice(device); + } + ::android::hardware::Return setAndGetVolume( + const ::android::hardware::hidl_vec& volumes, + setAndGetVolume_cb _hidl_cb) override { + return mEffect->setAndGetVolume(volumes, _hidl_cb); + } + ::android::hardware::Return volumeChangeNotification( + const ::android::hardware::hidl_vec& volumes) override { + return mEffect->volumeChangeNotification(volumes); + } + ::android::hardware::Return setAudioMode( + ::android::hardware::audio::common::V7_0::AudioMode mode) override { + return mEffect->setAudioMode(mode); + } + ::android::hardware::Return setConfigReverse( + const EffectConfig& config, + const ::android::sp& inputBufferProvider, + const ::android::sp& outputBufferProvider) override { + return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider); + } + ::android::hardware::Return setInputDevice( + const ::android::hardware::audio::common::V7_0::DeviceAddress& device) override { + return mEffect->setInputDevice(device); + } + ::android::hardware::Return getConfig(getConfig_cb _hidl_cb) override { + return mEffect->getConfig(_hidl_cb); + } + ::android::hardware::Return getConfigReverse(getConfigReverse_cb _hidl_cb) override { + return mEffect->getConfigReverse(_hidl_cb); + } + ::android::hardware::Return getSupportedAuxChannelsConfigs( + uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) override { + return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb); + } + ::android::hardware::Return getAuxChannelsConfig( + getAuxChannelsConfig_cb _hidl_cb) override { + return mEffect->getAuxChannelsConfig(_hidl_cb); + } + ::android::hardware::Return setAuxChannelsConfig( + const EffectAuxChannelsConfig& config) override { + return mEffect->setAuxChannelsConfig(config); + } + ::android::hardware::Return setAudioSource( + const ::android::hardware::hidl_string& source) override { + return mEffect->setAudioSource(source); + } + ::android::hardware::Return offload(const EffectOffloadParameter& param) override { + return mEffect->offload(param); + } + ::android::hardware::Return getDescriptor(getDescriptor_cb _hidl_cb) override { + return mEffect->getDescriptor(_hidl_cb); + } + ::android::hardware::Return prepareForProcessing( + prepareForProcessing_cb _hidl_cb) override { + return mEffect->prepareForProcessing(_hidl_cb); + } + ::android::hardware::Return setProcessBuffers(const AudioBuffer& inBuffer, + const AudioBuffer& outBuffer) override { + return mEffect->setProcessBuffers(inBuffer, outBuffer); + } + ::android::hardware::Return command(uint32_t commandId, + const ::android::hardware::hidl_vec& data, + uint32_t resultMaxSize, + command_cb _hidl_cb) override { + return mEffect->command(commandId, data, resultMaxSize, _hidl_cb); + } + ::android::hardware::Return setParameter( + const ::android::hardware::hidl_vec& parameter, + const ::android::hardware::hidl_vec& value) override { + return mEffect->setParameter(parameter, value); + } + ::android::hardware::Return getParameter( + const ::android::hardware::hidl_vec& parameter, uint32_t valueMaxSize, + getParameter_cb _hidl_cb) override { + return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb); + } + ::android::hardware::Return getSupportedConfigsForFeature( + uint32_t featureId, uint32_t maxConfigs, uint32_t configSize, + getSupportedConfigsForFeature_cb _hidl_cb) override { + return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb); + } + ::android::hardware::Return getCurrentConfigForFeature( + uint32_t featureId, uint32_t configSize, + getCurrentConfigForFeature_cb _hidl_cb) override { + return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb); + } + ::android::hardware::Return setCurrentConfigForFeature( + uint32_t featureId, const ::android::hardware::hidl_vec& configData) override { + return mEffect->setCurrentConfigForFeature(featureId, configData); + } + ::android::hardware::Return close() override { return mEffect->close(); } + + // Methods from IEqualizerEffect interface. + ::android::hardware::Return getNumBands(getNumBands_cb _hidl_cb) override; + ::android::hardware::Return getLevelRange(getLevelRange_cb _hidl_cb) override; + ::android::hardware::Return setBandLevel(uint16_t band, int16_t level) override; + ::android::hardware::Return getBandLevel(uint16_t band, + getBandLevel_cb _hidl_cb) override; + ::android::hardware::Return getBandCenterFrequency( + uint16_t band, getBandCenterFrequency_cb _hidl_cb) override; + ::android::hardware::Return getBandFrequencyRange( + uint16_t band, getBandFrequencyRange_cb _hidl_cb) override; + ::android::hardware::Return getBandForFrequency(uint32_t freq, + getBandForFrequency_cb _hidl_cb) override; + ::android::hardware::Return getPresetNames(getPresetNames_cb _hidl_cb) override; + ::android::hardware::Return setCurrentPreset(uint16_t preset) override; + ::android::hardware::Return getCurrentPreset(getCurrentPreset_cb _hidl_cb) override; + ::android::hardware::Return setAllProperties( + const IEqualizerEffect::AllProperties& properties) override; + ::android::hardware::Return getAllProperties(getAllProperties_cb _hidl_cb) override; + + private: + static constexpr size_t kNumBands = 1; + static constexpr size_t kNumPresets = 1; + sp mEffect; + IEqualizerEffect::AllProperties mProperties{}; +}; + +} // namespace android::hardware::audio::effect::V7_0::implementation diff --git a/audio/common/7.0/example/LoudnessEnhancerEffect.cpp b/audio/common/7.0/example/LoudnessEnhancerEffect.cpp new file mode 100644 index 0000000000..38269b3308 --- /dev/null +++ b/audio/common/7.0/example/LoudnessEnhancerEffect.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2020 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. + */ + +#define LOG_TAG "EffectsFactory7.0" +#include + +#include "LoudnessEnhancerEffect.h" + +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; +using namespace ::android::hardware::audio::common::V7_0; + +namespace android::hardware::audio::effect::V7_0::implementation { + +const EffectDescriptor& LoudnessEnhancerEffect::getDescriptor() { + // Note: for VTS tests only 'type' and 'uuid' fields are required. + // The actual implementation must provide meaningful values + // for all fields of the descriptor. + static const EffectDescriptor descriptor = { + .type = + {// Same UUID as AudioEffect.EFFECT_TYPE_LOUDNESS_ENHANCER in Java. + 0xfe3199be, 0xaed0, 0x413f, 0x87bb, + std::array{{0x11, 0x26, 0x0e, 0xb6, 0x3c, 0xf1}}}, + .uuid = {0, 0, 0, 2, std::array{{0, 0, 0, 0, 0, 0}}}}; + return descriptor; +} // namespace android::hardware::audio::effect::V7_0::implementation + +LoudnessEnhancerEffect::LoudnessEnhancerEffect() : mEffect(new Effect(getDescriptor())) {} + +Return LoudnessEnhancerEffect::setTargetGain(int32_t targetGainMb) { + mTargetGainMb = targetGainMb; + return Result::OK; +} + +Return LoudnessEnhancerEffect::getTargetGain(getTargetGain_cb _hidl_cb) { + _hidl_cb(Result::OK, mTargetGainMb); + return Void(); +} + +} // namespace android::hardware::audio::effect::V7_0::implementation diff --git a/audio/common/7.0/example/LoudnessEnhancerEffect.h b/audio/common/7.0/example/LoudnessEnhancerEffect.h new file mode 100644 index 0000000000..1af0d9f852 --- /dev/null +++ b/audio/common/7.0/example/LoudnessEnhancerEffect.h @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2020 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. + */ + +#pragma once + +#include + +#include "Effect.h" + +namespace android::hardware::audio::effect::V7_0::implementation { + +class LoudnessEnhancerEffect : public ILoudnessEnhancerEffect { + public: + static const EffectDescriptor& getDescriptor(); + + LoudnessEnhancerEffect(); + + // Methods from IEffect interface. + ::android::hardware::Return init() override { return mEffect->init(); } + ::android::hardware::Return setConfig( + const EffectConfig& config, + const ::android::sp& inputBufferProvider, + const ::android::sp& outputBufferProvider) override { + return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider); + } + ::android::hardware::Return reset() override { return mEffect->reset(); } + ::android::hardware::Return enable() override { return mEffect->enable(); } + ::android::hardware::Return disable() override { return mEffect->disable(); } + ::android::hardware::Return setDevice( + const ::android::hardware::audio::common::V7_0::DeviceAddress& device) override { + return mEffect->setDevice(device); + } + ::android::hardware::Return setAndGetVolume( + const ::android::hardware::hidl_vec& volumes, + setAndGetVolume_cb _hidl_cb) override { + return mEffect->setAndGetVolume(volumes, _hidl_cb); + } + ::android::hardware::Return volumeChangeNotification( + const ::android::hardware::hidl_vec& volumes) override { + return mEffect->volumeChangeNotification(volumes); + } + ::android::hardware::Return setAudioMode( + ::android::hardware::audio::common::V7_0::AudioMode mode) override { + return mEffect->setAudioMode(mode); + } + ::android::hardware::Return setConfigReverse( + const EffectConfig& config, + const ::android::sp& inputBufferProvider, + const ::android::sp& outputBufferProvider) override { + return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider); + } + ::android::hardware::Return setInputDevice( + const ::android::hardware::audio::common::V7_0::DeviceAddress& device) override { + return mEffect->setInputDevice(device); + } + ::android::hardware::Return getConfig(getConfig_cb _hidl_cb) override { + return mEffect->getConfig(_hidl_cb); + } + ::android::hardware::Return getConfigReverse(getConfigReverse_cb _hidl_cb) override { + return mEffect->getConfigReverse(_hidl_cb); + } + ::android::hardware::Return getSupportedAuxChannelsConfigs( + uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) override { + return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb); + } + ::android::hardware::Return getAuxChannelsConfig( + getAuxChannelsConfig_cb _hidl_cb) override { + return mEffect->getAuxChannelsConfig(_hidl_cb); + } + ::android::hardware::Return setAuxChannelsConfig( + const EffectAuxChannelsConfig& config) override { + return mEffect->setAuxChannelsConfig(config); + } + ::android::hardware::Return setAudioSource( + const ::android::hardware::hidl_string& source) override { + return mEffect->setAudioSource(source); + } + ::android::hardware::Return offload(const EffectOffloadParameter& param) override { + return mEffect->offload(param); + } + ::android::hardware::Return getDescriptor(getDescriptor_cb _hidl_cb) override { + return mEffect->getDescriptor(_hidl_cb); + } + ::android::hardware::Return prepareForProcessing( + prepareForProcessing_cb _hidl_cb) override { + return mEffect->prepareForProcessing(_hidl_cb); + } + ::android::hardware::Return setProcessBuffers(const AudioBuffer& inBuffer, + const AudioBuffer& outBuffer) override { + return mEffect->setProcessBuffers(inBuffer, outBuffer); + } + ::android::hardware::Return command(uint32_t commandId, + const ::android::hardware::hidl_vec& data, + uint32_t resultMaxSize, + command_cb _hidl_cb) override { + return mEffect->command(commandId, data, resultMaxSize, _hidl_cb); + } + ::android::hardware::Return setParameter( + const ::android::hardware::hidl_vec& parameter, + const ::android::hardware::hidl_vec& value) override { + return mEffect->setParameter(parameter, value); + } + ::android::hardware::Return getParameter( + const ::android::hardware::hidl_vec& parameter, uint32_t valueMaxSize, + getParameter_cb _hidl_cb) override { + return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb); + } + ::android::hardware::Return getSupportedConfigsForFeature( + uint32_t featureId, uint32_t maxConfigs, uint32_t configSize, + getSupportedConfigsForFeature_cb _hidl_cb) override { + return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb); + } + ::android::hardware::Return getCurrentConfigForFeature( + uint32_t featureId, uint32_t configSize, + getCurrentConfigForFeature_cb _hidl_cb) override { + return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb); + } + ::android::hardware::Return setCurrentConfigForFeature( + uint32_t featureId, const ::android::hardware::hidl_vec& configData) override { + return mEffect->setCurrentConfigForFeature(featureId, configData); + } + ::android::hardware::Return close() override { return mEffect->close(); } + + // Methods from ILoudnessEnhancerEffect interface. + ::android::hardware::Return setTargetGain(int32_t targetGainMb) override; + ::android::hardware::Return getTargetGain(getTargetGain_cb _hidl_cb) override; + + private: + sp mEffect; + int32_t mTargetGainMb = 0; +}; + +} // namespace android::hardware::audio::effect::V7_0::implementation diff --git a/audio/common/7.0/example/android.hardware.audio@7.0-service.example.rc b/audio/common/7.0/example/android.hardware.audio@7.0-service.example.rc new file mode 100644 index 0000000000..cf8b51f07b --- /dev/null +++ b/audio/common/7.0/example/android.hardware.audio@7.0-service.example.rc @@ -0,0 +1,7 @@ +service vendor.audio-hal-7-0 /vendor/bin/hw/android.hardware.audio@7.0-service.example + class hal + user audioserver + group audio + capabilities BLOCK_SUSPEND + ioprio rt 4 + task_profiles ProcessCapacityHigh HighPerformance diff --git a/audio/common/7.0/example/android.hardware.audio@7.0-service.example.xml b/audio/common/7.0/example/android.hardware.audio@7.0-service.example.xml new file mode 100644 index 0000000000..b91b0612ce --- /dev/null +++ b/audio/common/7.0/example/android.hardware.audio@7.0-service.example.xml @@ -0,0 +1,20 @@ + + + android.hardware.audio + hwbinder + 7.0 + + IDevicesFactory + example + + + + android.hardware.audio.effect + hwbinder + 7.0 + + IEffectsFactory + example + + + diff --git a/audio/common/7.0/example/service.cpp b/audio/common/7.0/example/service.cpp new file mode 100644 index 0000000000..641e2c90ae --- /dev/null +++ b/audio/common/7.0/example/service.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2020 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. + */ + +#define LOG_TAG "android.hardware.audio@7.0-service.example" +#include +#include + +#include "DevicesFactory.h" +#include "EffectsFactory.h" + +using android::hardware::configureRpcThreadpool; +using android::hardware::joinRpcThreadpool; +using namespace android; + +status_t registerDevicesFactoryService() { + sp<::android::hardware::audio::V7_0::IDevicesFactory> devicesFactory = + new ::android::hardware::audio::V7_0::implementation::DevicesFactory(); + status_t status = devicesFactory->registerAsService("example"); + ALOGE_IF(status != OK, "Error registering devices factory as service: %d", status); + return status; +} + +status_t registerEffectsFactoryService() { + sp<::android::hardware::audio::effect::V7_0::IEffectsFactory> devicesFactory = + new ::android::hardware::audio::effect::V7_0::implementation::EffectsFactory(); + status_t status = devicesFactory->registerAsService("example"); + ALOGE_IF(status != OK, "Error registering effects factory as service: %d", status); + return status; +} + +int main() { + configureRpcThreadpool(1, true); + status_t status = registerDevicesFactoryService(); + if (status != OK) { + return status; + } + status = registerEffectsFactoryService(); + if (status != OK) { + return status; + } + joinRpcThreadpool(); + + return 1; +} diff --git a/audio/common/7.0/types.hal b/audio/common/7.0/types.hal index 94d0af7673..31c7388329 100644 --- a/audio/common/7.0/types.hal +++ b/audio/common/7.0/types.hal @@ -112,12 +112,28 @@ typedef string AudioFormat; typedef string AudioChannelMask; /** - * Basic configuration applicable to any stream of audio. + * Base configuration attributes applicable to any stream of audio. */ -struct AudioBasicConfig { +struct AudioConfigBase { + AudioFormat format; // 'DEFAULT' means 'unspecified' uint32_t sampleRateHz; // 0 means 'unspecified' vec channelMask; // empty means 'unspecified' - AudioFormat format; // 'DEFAULT' means 'unspecified' +}; + +/** + * Configurations supported for a certain audio format. + */ +struct AudioProfile { + AudioFormat format; + /** List of the sample rates (in Hz) supported by the profile. */ + vec sampleRates; + /** + * List of channel masks supported by the profile. Every subvector might be + * comprised of several individual channel mask entries for non-traditional + * channel masks, e.g. a combination "OUT_FRONT_LEFT,OUT_FRONT_CENTER" which + * doesn't have a corresponding predefined channel mask. + */ + vec> channelMasks; }; /** @@ -136,18 +152,21 @@ enum AudioMode : int32_t { CALL_SCREEN = 4, }; +/** + * Audio device specifies type (or category) of audio I/O device + * (e.g. speaker or headphones). + * See 'audioDevice' in audio_policy_configuration.xsd for the + * list of allowed values. + */ +typedef string AudioDevice; + /** * Specifies a device address in case when several devices of the same type * can be connected (e.g. BT A2DP, USB). */ struct DeviceAddress { - /** - * Audio device specifies type (or category) of audio I/O device - * (e.g. speaker or headphones). - * See 'audioDevice' in audio_policy_configuration.xsd for the - * list of allowed values. - */ - string deviceType; + /** The type of the device. */ + AudioDevice deviceType; safe_union Address { /** * The address may be left unspecified if 'device' specifies @@ -209,7 +228,7 @@ enum AudioEncapsulationMode : int32_t { * Additional information about the stream passed to hardware decoders. */ struct AudioOffloadInfo { - AudioBasicConfig base; + AudioConfigBase base; AudioStreamType streamType; uint32_t bitRatePerSecond; int64_t durationMicroseconds; // -1 if unknown @@ -227,7 +246,7 @@ struct AudioOffloadInfo { * Commonly used audio stream configuration parameters. */ struct AudioConfig { - AudioBasicConfig base; + AudioConfigBase base; AudioOffloadInfo offloadInfo; uint64_t frameCount; }; @@ -372,9 +391,9 @@ struct AudioPortConfig { /** * Basic parameters: sampling rate, format, channel mask. Only some of the * parameters (or none) may be set. See the documentation of the - * AudioBasicConfig struct. + * AudioConfigBase struct. */ - AudioBasicConfig config; + AudioConfigBase config; /** Associated gain control. */ safe_union OptionalGain { Monostate unspecified; @@ -401,13 +420,6 @@ struct AudioPort { */ string name; /** List of audio profiles supported by the port. */ - struct AudioProfile { - AudioFormat format; - /** List of the sample rates supported by the profile. */ - vec sampleRates; - /** List of channel masks supported by the profile. */ - vec channelMasks; - }; vec profiles; /** List of gain controls attached to the port. */ vec gains; diff --git a/audio/common/all-versions/default/VersionUtils.h b/audio/common/all-versions/default/VersionUtils.h index e7755b1a7a..9bfca0cdcc 100644 --- a/audio/common/all-versions/default/VersionUtils.h +++ b/audio/common/all-versions/default/VersionUtils.h @@ -31,7 +31,7 @@ typedef common::CPP_VERSION::AudioDevice AudioDeviceBitfield; typedef common::CPP_VERSION::AudioChannelMask AudioChannelBitfield; typedef common::CPP_VERSION::AudioOutputFlag AudioOutputFlagBitfield; typedef common::CPP_VERSION::AudioInputFlag AudioInputFlagBitfield; -#elif MAJOR_VERSION >= 4 +#elif MAJOR_VERSION >= 4 && MAJOR_VERSION <= 6 typedef hidl_bitfield AudioDeviceBitfield; typedef hidl_bitfield AudioChannelBitfield; typedef hidl_bitfield AudioOutputFlagBitfield; diff --git a/audio/core/all-versions/default/include/core/default/Device.h b/audio/core/all-versions/default/include/core/default/Device.h index b0e72d9600..907acd7d7d 100644 --- a/audio/core/all-versions/default/include/core/default/Device.h +++ b/audio/core/all-versions/default/include/core/default/Device.h @@ -43,8 +43,10 @@ using ::android::hardware::hidl_string; using ::android::hardware::hidl_vec; using ::android::hardware::Return; using ::android::hardware::Void; +#if MAJOR_VERSION <= 6 using ::android::hardware::audio::common::CPP_VERSION::implementation::AudioInputFlagBitfield; using ::android::hardware::audio::common::CPP_VERSION::implementation::AudioOutputFlagBitfield; +#endif using namespace ::android::hardware::audio::common::CPP_VERSION; using namespace ::android::hardware::audio::CPP_VERSION; diff --git a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp index b0eb2e0cfb..2466fd120a 100644 --- a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp +++ b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp @@ -16,6 +16,13 @@ #include "AudioPrimaryHidlHalTest.h" +#if MAJOR_VERSION >= 7 +#include +#include + +using android::xsdc_enum_range; +#endif + TEST_P(AudioHidlTest, OpenPrimaryDeviceUsingGetDevice) { doc::test("Calling openDevice(\"primary\") should return the primary device."); if (getDeviceName() != DeviceManager::kPrimaryDevice) { @@ -53,14 +60,29 @@ TEST_P(AudioHidlDeviceTest, GetMicrophonesTest) { "Make sure getMicrophones always succeeds" "and getActiveMicrophones always succeeds when recording from these microphones."); AudioConfig config{}; +#if MAJOR_VERSION <= 6 config.channelMask = mkEnumBitfield(AudioChannelMask::IN_MONO); config.sampleRateHz = 8000; config.format = AudioFormat::PCM_16_BIT; auto flags = hidl_bitfield(AudioInputFlag::NONE); const SinkMetadata initMetadata = {{{.source = AudioSource::MIC, .gain = 1}}}; +#elif MAJOR_VERSION >= 7 + config.base.channelMask.resize(1); + config.base.channelMask[0] = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_IN_MONO); + config.base.sampleRateHz = 8000; + config.base.format = toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT); + hidl_vec flags; + const SinkMetadata initMetadata = { + {{.source = toString(xsd::AudioSource::AUDIO_SOURCE_MIC), .gain = 1}}}; +#endif EventFlag* efGroup; for (auto microphone : microphones) { +#if MAJOR_VERSION <= 6 if (microphone.deviceAddress.device != AudioDevice::IN_BUILTIN_MIC) { +#elif MAJOR_VERSION >= 7 + if (xsd::stringToAudioDevice(microphone.deviceAddress.deviceType) != + xsd::AudioDevice::AUDIO_DEVICE_IN_BUILTIN_MIC) { +#endif continue; } sp stream; @@ -81,16 +103,16 @@ TEST_P(AudioHidlDeviceTest, GetMicrophonesTest) { size_t frameSize = stream->getFrameSize(); size_t frameCount = stream->getBufferSize() / frameSize; ASSERT_OK(stream->prepareForReading( - frameSize, frameCount, [&](auto r, auto& c, auto& d, auto&, auto&) { - readRes = r; - if (readRes == Result::OK) { - commandMQ.reset(new CommandMQ(c)); - dataMQ.reset(new DataMQ(d)); - if (dataMQ->isValid() && dataMQ->getEventFlagWord()) { - EventFlag::createEventFlag(dataMQ->getEventFlagWord(), &efGroup); + frameSize, frameCount, [&](auto r, auto& c, auto& d, auto&, auto) { + readRes = r; + if (readRes == Result::OK) { + commandMQ.reset(new CommandMQ(c)); + dataMQ.reset(new DataMQ(d)); + if (dataMQ->isValid() && dataMQ->getEventFlagWord()) { + EventFlag::createEventFlag(dataMQ->getEventFlagWord(), &efGroup); + } } - } - })); + })); ASSERT_OK(readRes); IStreamIn::ReadParameters params; params.command = IStreamIn::ReadCommand::READ; @@ -116,13 +138,24 @@ TEST_P(AudioHidlDeviceTest, GetMicrophonesTest) { TEST_P(AudioHidlDeviceTest, SetConnectedState) { doc::test("Check that the HAL can be notified of device connection and deconnection"); +#if MAJOR_VERSION <= 6 using AD = AudioDevice; for (auto deviceType : {AD::OUT_HDMI, AD::OUT_WIRED_HEADPHONE, AD::IN_USB_HEADSET}) { +#elif MAJOR_VERSION >= 7 + using AD = xsd::AudioDevice; + for (auto deviceType : + {toString(AD::AUDIO_DEVICE_OUT_HDMI), toString(AD::AUDIO_DEVICE_OUT_WIRED_HEADPHONE), + toString(AD::AUDIO_DEVICE_IN_USB_HEADSET)}) { +#endif SCOPED_TRACE("device=" + ::testing::PrintToString(deviceType)); for (bool state : {true, false}) { SCOPED_TRACE("state=" + ::testing::PrintToString(state)); DeviceAddress address = {}; +#if MAJOR_VERSION <= 6 address.device = deviceType; +#elif MAJOR_VERSION >= 7 + address.deviceType = deviceType; +#endif auto ret = getDevice()->setConnectedState(address, state); ASSERT_TRUE(ret.isOk()); if (ret == Result::NOT_SUPPORTED) { @@ -148,7 +181,11 @@ static void testGetDevices(IStream* stream, AudioDevice expectedDevice) { } // The stream was constructed with one device, thus getDevices must only return one ASSERT_EQ(1U, devices.size()); +#if MAJOR_VERSION <= 6 AudioDevice device = devices[0].device; +#elif MAJOR_VERSION >= 7 + auto device = devices[0].deviceType; +#endif ASSERT_TRUE(device == expectedDevice) << "Expected: " << ::testing::PrintToString(expectedDevice) << "\n Actual: " << ::testing::PrintToString(device); @@ -156,12 +193,22 @@ static void testGetDevices(IStream* stream, AudioDevice expectedDevice) { TEST_IO_STREAM(GetDevices, "Check that the stream device == the one it was opened with", areAudioPatchesSupported() ? doc::partialTest("Audio patches are supported") +#if MAJOR_VERSION <= 6 : testGetDevices(stream.get(), address.device)) +#elif MAJOR_VERSION >= 7 + : testGetDevices(stream.get(), address.deviceType)) +#endif static void testSetDevices(IStream* stream, const DeviceAddress& address) { DeviceAddress otherAddress = address; +#if MAJOR_VERSION <= 6 otherAddress.device = (address.device & AudioDevice::BIT_IN) == 0 ? AudioDevice::OUT_SPEAKER : AudioDevice::IN_BUILTIN_MIC; +#elif MAJOR_VERSION >= 7 + otherAddress.deviceType = xsd::isOutputDevice(address.deviceType) + ? toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_SPEAKER) + : toString(xsd::AudioDevice::AUDIO_DEVICE_IN_BUILTIN_MIC); +#endif EXPECT_RESULT(okOrNotSupported, stream->setDevices({otherAddress})); ASSERT_RESULT(okOrNotSupported, @@ -186,11 +233,19 @@ TEST_IO_STREAM(GetHwAvSync, "Get hardware sync can not fail", checkGetHwAVSync(g TEST_P(InputStreamTest, updateSinkMetadata) { doc::test("The HAL should not crash on metadata change"); +#if MAJOR_VERSION <= 6 hidl_enum_range range; +#elif MAJOR_VERSION >= 7 + xsdc_enum_range range; +#endif // Test all possible track configuration - for (AudioSource source : range) { + for (auto source : range) { for (float volume : {0.0, 0.5, 1.0}) { +#if MAJOR_VERSION <= 6 const SinkMetadata metadata = {{{.source = source, .gain = volume}}}; +#elif MAJOR_VERSION >= 7 + const SinkMetadata metadata = {{{.source = toString(source), .gain = volume}}}; +#endif ASSERT_OK(stream->updateSinkMetadata(metadata)) << "source=" << toString(source) << ", volume=" << volume; } @@ -213,13 +268,22 @@ TEST_P(OutputStreamTest, SelectPresentation) { TEST_P(OutputStreamTest, updateSourceMetadata) { doc::test("The HAL should not crash on metadata change"); +#if MAJOR_VERSION <= 6 hidl_enum_range usageRange; hidl_enum_range contentRange; +#elif MAJOR_VERSION >= 7 + xsdc_enum_range usageRange; + xsdc_enum_range contentRange; +#endif // Test all possible track configuration for (auto usage : usageRange) { for (auto content : contentRange) { for (float volume : {0.0, 0.5, 1.0}) { +#if MAJOR_VERSION <= 6 const SourceMetadata metadata = {{{usage, content, volume}}}; +#elif MAJOR_VERSION >= 7 + const SourceMetadata metadata = {{{toString(usage), toString(content), volume}}}; +#endif ASSERT_OK(stream->updateSourceMetadata(metadata)) << "usage=" << toString(usage) << ", content=" << toString(content) << ", volume=" << volume; @@ -227,12 +291,26 @@ TEST_P(OutputStreamTest, updateSourceMetadata) { } } + // clang-format off // Set many track of different configuration ASSERT_OK(stream->updateSourceMetadata( +#if MAJOR_VERSION <= 6 {{{AudioUsage::MEDIA, AudioContentType::MUSIC, 0.1}, {AudioUsage::VOICE_COMMUNICATION, AudioContentType::SPEECH, 1.0}, {AudioUsage::ALARM, AudioContentType::SONIFICATION, 0.0}, - {AudioUsage::ASSISTANT, AudioContentType::UNKNOWN, 0.3}}})); + {AudioUsage::ASSISTANT, AudioContentType::UNKNOWN, 0.3}}} +#elif MAJOR_VERSION >= 7 + {{{toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA), + toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_MUSIC), 0.1}, + {toString(xsd::AudioUsage::AUDIO_USAGE_VOICE_COMMUNICATION), + toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_SPEECH), 1.0}, + {toString(xsd::AudioUsage::AUDIO_USAGE_ALARM), + toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_SONIFICATION), 0.0}, + {toString(xsd::AudioUsage::AUDIO_USAGE_ASSISTANT), + toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_UNKNOWN), 0.3}}} +#endif + )); + // clang-format on // Set no metadata as if all stream track had stopped ASSERT_OK(stream->updateSourceMetadata({})); diff --git a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalUtils.h b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalUtils.h index 7a52d0e364..81a1f7b4b7 100644 --- a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalUtils.h +++ b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalUtils.h @@ -56,6 +56,7 @@ struct Parameters { } }; +#if MAJOR_VERSION <= 6 struct GetSupported { static auto getFormat(IStream* stream) { auto ret = stream->getFormat(); @@ -80,7 +81,7 @@ struct GetSupported { EXPECT_OK(stream->getSupportedFormats(returnIn(capabilities))); return Result::OK; } -#elif MAJOR_VERSION >= 6 +#else // MAJOR_VERSION == 6 static Result formats(IStream* stream, hidl_vec& capabilities) { Result res; EXPECT_OK(stream->getSupportedFormats(returnIn(res, capabilities))); @@ -88,6 +89,7 @@ struct GetSupported { } #endif }; +#endif // MAJOR_VERSION <= 6 template auto dump(T t, hidl_handle handle) { diff --git a/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp index 54d4bbd2cc..bd8de2d0e6 100644 --- a/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp +++ b/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp @@ -17,6 +17,7 @@ // pull in all the <= 5.0 tests #include "5.0/AudioPrimaryHidlHalTest.cpp" +#if MAJOR_VERSION <= 6 const std::vector& getOutputDeviceConfigParameters() { static std::vector parameters = [] { std::vector result; @@ -28,8 +29,8 @@ const std::vector& getOutputDeviceConfigParameters() { const auto& channels = profile->getChannels(); const auto& sampleRates = profile->getSampleRates(); auto configs = ConfigHelper::combineAudioConfig( - vector(channels.begin(), channels.end()), - vector(sampleRates.begin(), sampleRates.end()), + std::vector(channels.begin(), channels.end()), + std::vector(sampleRates.begin(), sampleRates.end()), profile->getFormat()); auto flags = ioProfile->getFlags(); for (auto& config : configs) { @@ -46,8 +47,8 @@ const std::vector& getOutputDeviceConfigParameters() { config.offloadInfo.bufferSize = 256; // arbitrary value config.offloadInfo.usage = AudioUsage::MEDIA; result.emplace_back(device, config, - AudioOutputFlag(AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD | - AUDIO_OUTPUT_FLAG_DIRECT)); + AudioOutputFlag(AudioOutputFlag::COMPRESS_OFFLOAD | + AudioOutputFlag::DIRECT)); } else { if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) { // ignore the flag flags &= ~AUDIO_OUTPUT_FLAG_PRIMARY; @@ -74,8 +75,8 @@ const std::vector& getInputDeviceConfigParameters() { const auto& channels = profile->getChannels(); const auto& sampleRates = profile->getSampleRates(); auto configs = ConfigHelper::combineAudioConfig( - vector(channels.begin(), channels.end()), - vector(sampleRates.begin(), sampleRates.end()), + std::vector(channels.begin(), channels.end()), + std::vector(sampleRates.begin(), sampleRates.end()), profile->getFormat()); for (const auto& config : configs) { result.emplace_back(device, config, AudioInputFlag(ioProfile->getFlags())); @@ -87,13 +88,22 @@ const std::vector& getInputDeviceConfigParameters() { }(); return parameters; } +#endif // MAJOR_VERSION <= 6 TEST_P(AudioHidlDeviceTest, CloseDeviceWithOpenedOutputStreams) { doc::test("Verify that a device can't be closed if there are streams opened"); +#if MAJOR_VERSION <= 6 DeviceAddress address{.device = AudioDevice::OUT_DEFAULT}; - AudioConfig config{}; - auto flags = hidl_bitfield(AudioOutputFlag::NONE); SourceMetadata initMetadata = {{{AudioUsage::MEDIA, AudioContentType::MUSIC, 1 /* gain */}}}; + auto flags = hidl_bitfield(AudioOutputFlag::NONE); +#elif MAJOR_VERSION >= 7 + DeviceAddress address{.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_DEFAULT)}; + SourceMetadata initMetadata = { + {{toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA), + toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_MUSIC), 1 /* gain */}}}; + hidl_vec flags; +#endif + AudioConfig config{}; sp stream; StreamHelper helper(stream); AudioConfig suggestedConfig{}; @@ -111,14 +121,20 @@ TEST_P(AudioHidlDeviceTest, CloseDeviceWithOpenedOutputStreams) { TEST_P(AudioHidlDeviceTest, CloseDeviceWithOpenedInputStreams) { doc::test("Verify that a device can't be closed if there are streams opened"); - auto module = getCachedPolicyConfig().getModuleFromName(getDeviceName()); - if (module->getInputProfiles().empty()) { + if (!getCachedPolicyConfig().haveInputProfilesInModule(getDeviceName())) { GTEST_SKIP() << "Device doesn't have input profiles"; } +#if MAJOR_VERSION <= 6 DeviceAddress address{.device = AudioDevice::IN_DEFAULT}; - AudioConfig config{}; - auto flags = hidl_bitfield(AudioInputFlag::NONE); SinkMetadata initMetadata = {{{.source = AudioSource::MIC, .gain = 1}}}; + auto flags = hidl_bitfield(AudioInputFlag::NONE); +#elif MAJOR_VERSION >= 7 + DeviceAddress address{.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_IN_DEFAULT)}; + SinkMetadata initMetadata = { + {{.source = toString(xsd::AudioSource::AUDIO_SOURCE_MIC), .gain = 1}}}; + hidl_vec flags; +#endif + AudioConfig config{}; sp stream; StreamHelper helper(stream); AudioConfig suggestedConfig{}; @@ -137,9 +153,8 @@ TEST_P(AudioHidlDeviceTest, CloseDeviceWithOpenedInputStreams) { TEST_P(AudioPatchHidlTest, UpdatePatchInvalidHandle) { doc::test("Verify that passing an invalid handle to updateAudioPatch is checked"); AudioPatchHandle ignored; - ASSERT_OK(getDevice()->updateAudioPatch( - static_cast(AudioHandleConsts::AUDIO_PATCH_HANDLE_NONE), - hidl_vec(), hidl_vec(), returnIn(res, ignored))); + ASSERT_OK(getDevice()->updateAudioPatch(AudioPatchHandle{}, hidl_vec(), + hidl_vec(), returnIn(res, ignored))); ASSERT_RESULT(Result::INVALID_ARGUMENTS, res); } diff --git a/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp index 33efa6f4d6..63eaea8acc 100644 --- a/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp +++ b/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp @@ -16,3 +16,101 @@ // pull in all the <= 6.0 tests #include "6.0/AudioPrimaryHidlHalTest.cpp" + +static std::vector combineAudioConfig(std::vector channelMasks, + std::vector sampleRates, + const std::string& format) { + std::vector configs; + configs.reserve(channelMasks.size() * sampleRates.size()); + for (auto channelMask : channelMasks) { + for (auto sampleRate : sampleRates) { + AudioConfig config{}; + // leave offloadInfo to 0 + config.base.channelMask.resize(1); + config.base.channelMask[0] = toString(channelMask); + config.base.sampleRateHz = sampleRate; + config.base.format = format; + configs.push_back(config); + } + } + return configs; +} + +const std::vector& getOutputDeviceConfigParameters() { + static std::vector parameters = [] { + std::vector result; + const std::vector offloadFlags = { + toString(xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD), + toString(xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_DIRECT)}; + for (const auto& device : getDeviceParameters()) { + auto module = + getCachedPolicyConfig().getModuleFromName(std::get(device)); + for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) { + if (mixPort.getRole() != xsd::Role::source) continue; // not an output profile + auto xsdFlags = mixPort.getFlags(); + const bool isOffload = + std::find(xsdFlags.begin(), xsdFlags.end(), + xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != + xsdFlags.end(); + std::vector flags; + if (!isOffload) { + for (auto flag : xsdFlags) { + if (flag != xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_PRIMARY) { + flags.push_back(toString(flag)); + } + } + } else { + flags = offloadFlags; + } + for (const auto& profile : mixPort.getProfile()) { + auto configs = + combineAudioConfig(profile.getChannelMasks(), + profile.getSamplingRates(), profile.getFormat()); + for (auto& config : configs) { + // Some combinations of flags declared in the config file require special + // treatment. + if (isOffload) { + config.offloadInfo.base = config.base; + config.offloadInfo.streamType = + toString(xsd::AudioStreamType::AUDIO_STREAM_MUSIC); + config.offloadInfo.usage = toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA); + config.offloadInfo.bitRatePerSecond = 320; + config.offloadInfo.durationMicroseconds = -1; + config.offloadInfo.bitWidth = 16; + config.offloadInfo.bufferSize = 256; // arbitrary value + } + result.emplace_back(device, config, flags); + } + } + } + } + return result; + }(); + return parameters; +} + +const std::vector& getInputDeviceConfigParameters() { + static std::vector parameters = [] { + std::vector result; + for (const auto& device : getDeviceParameters()) { + auto module = + getCachedPolicyConfig().getModuleFromName(std::get(device)); + for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) { + if (mixPort.getRole() != xsd::Role::sink) continue; // not an input profile + std::vector flags; + std::transform(mixPort.getFlags().begin(), mixPort.getFlags().end(), flags.begin(), + [](auto flag) { return toString(flag); }); + for (const auto& profile : mixPort.getProfile()) { + auto configs = + combineAudioConfig(profile.getChannelMasks(), + profile.getSamplingRates(), profile.getFormat()); + for (const auto& config : configs) { + result.emplace_back(device, config, flags); + } + } + } + } + return result; + }(); + return parameters; +} diff --git a/audio/core/all-versions/vts/functional/7.0/PolicyConfig.h b/audio/core/all-versions/vts/functional/7.0/PolicyConfig.h new file mode 100644 index 0000000000..d790b34c46 --- /dev/null +++ b/audio/core/all-versions/vts/functional/7.0/PolicyConfig.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2020 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. + */ + +#pragma once + +// Note: it is assumed that this file is included from AudioPrimaryHidlTest.h +// and thus it doesn't have all '#include' and 'using' directives required +// for a standalone compilation. + +namespace xsd { +using Module = Modules::Module; +} + +class PolicyConfig { + public: + explicit PolicyConfig(const std::string& configFileName) + : mConfigFileName{configFileName}, + mFilePath{findExistingConfigurationFile(mConfigFileName)}, + mConfig{xsd::read(mFilePath.c_str())} { + if (mConfig) { + mStatus = OK; + mPrimaryModule = getModuleFromName(DeviceManager::kPrimaryDevice); + for (const auto& module : mConfig->getFirstModules()->get_module()) { + auto attachedDevices = module.getFirstAttachedDevices()->getItem(); + if (!attachedDevices.empty()) { + mModulesWithDevicesNames.insert(module.getName()); + } + } + } + } + status_t getStatus() const { return mStatus; } + std::string getError() const { + if (mFilePath.empty()) { + return std::string{"Could not find "} + mConfigFileName + + " file in: " + testing::PrintToString(android::audio_get_configuration_paths()); + } else { + return "Invalid config file: " + mFilePath; + } + } + const std::string& getFilePath() const { return mFilePath; } + const xsd::Module* getModuleFromName(const std::string& name) const { + if (mConfig) { + for (const auto& module : mConfig->getFirstModules()->get_module()) { + if (module.getName() == name) return &module; + } + } + return nullptr; + } + const xsd::Module* getPrimaryModule() const { return mPrimaryModule; } + const std::set& getModulesWithDevicesNames() const { + return mModulesWithDevicesNames; + } + bool haveInputProfilesInModule(const std::string& name) const { + auto module = getModuleFromName(name); + for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) { + if (mixPort.getRole() == xsd::Role::sink) return true; + } + return false; + } + + private: + static std::string findExistingConfigurationFile(const std::string& fileName) { + for (const auto& location : android::audio_get_configuration_paths()) { + std::string path = location + '/' + fileName; + if (access(path.c_str(), F_OK) == 0) { + return path; + } + } + return std::string{}; + } + + const std::string mConfigFileName; + const std::string mFilePath; + std::optional mConfig; + status_t mStatus = NO_INIT; + const xsd::Module* mPrimaryModule; + std::set mModulesWithDevicesNames; +}; diff --git a/audio/core/all-versions/vts/functional/Android.bp b/audio/core/all-versions/vts/functional/Android.bp index 6ac9b20f95..c7bfe08889 100644 --- a/audio/core/all-versions/vts/functional/Android.bp +++ b/audio/core/all-versions/vts/functional/Android.bp @@ -19,9 +19,6 @@ cc_defaults { defaults: ["VtsHalTargetTestDefaults"], static_libs: [ "android.hardware.audio.common.test.utility", - "libaudiofoundation", - "libaudiopolicycomponents", - "libmedia_helper", "libxml2", ], shared_libs: [ @@ -44,6 +41,9 @@ cc_test { "2.0/AudioPrimaryHidlHalTest.cpp", ], static_libs: [ + "libaudiofoundation", + "libaudiopolicycomponents", + "libmedia_helper", "android.hardware.audio@2.0", "android.hardware.audio.common@2.0", ], @@ -67,6 +67,9 @@ cc_test { "4.0/AudioPrimaryHidlHalTest.cpp", ], static_libs: [ + "libaudiofoundation", + "libaudiopolicycomponents", + "libmedia_helper", "android.hardware.audio@4.0", "android.hardware.audio.common@4.0", ], @@ -90,6 +93,9 @@ cc_test { "5.0/AudioPrimaryHidlHalTest.cpp", ], static_libs: [ + "libaudiofoundation", + "libaudiopolicycomponents", + "libmedia_helper", "android.hardware.audio@5.0", "android.hardware.audio.common@5.0", ], @@ -113,6 +119,9 @@ cc_test { "6.0/AudioPrimaryHidlHalTest.cpp", ], static_libs: [ + "libaudiofoundation", + "libaudiopolicycomponents", + "libmedia_helper", "android.hardware.audio@6.0", "android.hardware.audio.common@6.0", ], @@ -130,7 +139,6 @@ cc_test { } cc_test { - enabled: false, name: "VtsHalAudioV7_0TargetTest", defaults: ["VtsHalAudioTargetTest_defaults"], srcs: [ @@ -139,6 +147,7 @@ cc_test { static_libs: [ "android.hardware.audio@7.0", "android.hardware.audio.common@7.0", + "android.hardware.audio.common@7.0-enums", ], cflags: [ "-DMAJOR_VERSION=7", diff --git a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h index 01bdd69408..5e4b414d29 100644 --- a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h +++ b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h @@ -42,8 +42,11 @@ #include PATH(android/hardware/audio/FILE_VERSION/IPrimaryDevice.h) #include PATH(android/hardware/audio/FILE_VERSION/types.h) #include PATH(android/hardware/audio/common/FILE_VERSION/types.h) +#if MAJOR_VERSION >= 7 +#include +#include +#endif -#include #include #include #include @@ -63,14 +66,6 @@ #include "4.0/AudioPrimaryHidlHalUtils.h" #endif -using std::initializer_list; -using std::list; -using std::string; -using std::to_string; -using std::vector; - -using ::android::AudioPolicyConfig; -using ::android::HwModule; using ::android::NO_INIT; using ::android::OK; using ::android::sp; @@ -93,6 +88,12 @@ using ::android::hardware::details::toHexString; using namespace ::android::hardware::audio::common::CPP_VERSION; using namespace ::android::hardware::audio::common::test::utility; using namespace ::android::hardware::audio::CPP_VERSION; +#if MAJOR_VERSION >= 7 +// Make an alias for enumerations generated from the APM config XSD. +namespace xsd { +using namespace ::audio::policy::configuration::CPP_VERSION; +} +#endif // Typical accepted results from interface methods static auto okOrNotSupported = {Result::OK, Result::NOT_SUPPORTED}; @@ -103,8 +104,12 @@ static auto okOrInvalidStateOrNotSupported = {Result::OK, Result::INVALID_STATE, static auto invalidArgsOrNotSupported = {Result::INVALID_ARGUMENTS, Result::NOT_SUPPORTED}; static auto invalidStateOrNotSupported = {Result::INVALID_STATE, Result::NOT_SUPPORTED}; -#define AUDIO_PRIMARY_HIDL_HAL_TEST #include "DeviceManager.h" +#if MAJOR_VERSION <= 6 +#include "PolicyConfig.h" +#elif MAJOR_VERSION >= 7 +#include "7.0/PolicyConfig.h" +#endif class HidlTest : public ::testing::Test { public: @@ -136,83 +141,16 @@ class HidlTest : public ::testing::Test { ////////////////////////// Audio policy configuration //////////////////////// ////////////////////////////////////////////////////////////////////////////// -static constexpr char kConfigFileName[] = "audio_policy_configuration.xml"; - // Stringify the argument. #define QUOTE(x) #x #define STRINGIFY(x) QUOTE(x) -struct PolicyConfigData { - android::HwModuleCollection hwModules; - android::DeviceVector availableOutputDevices; - android::DeviceVector availableInputDevices; - sp defaultOutputDevice; -}; - -class PolicyConfig : private PolicyConfigData, public AudioPolicyConfig { - public: - PolicyConfig() - : AudioPolicyConfig(hwModules, availableOutputDevices, availableInputDevices, - defaultOutputDevice) { - for (const auto& location : android::audio_get_configuration_paths()) { - std::string path = location + '/' + kConfigFileName; - if (access(path.c_str(), F_OK) == 0) { - mFilePath = path; - break; - } - } - mStatus = android::deserializeAudioPolicyFile(mFilePath.c_str(), this); - if (mStatus == OK) { - mPrimaryModule = getHwModules().getModuleFromName(DeviceManager::kPrimaryDevice); - // Available devices are not 'attached' to modules at this moment. - // Need to go over available devices and find their module. - for (const auto& device : availableOutputDevices) { - for (const auto& module : hwModules) { - if (module->getDeclaredDevices().indexOf(device) >= 0) { - mModulesWithDevicesNames.insert(module->getName()); - break; - } - } - } - for (const auto& device : availableInputDevices) { - for (const auto& module : hwModules) { - if (module->getDeclaredDevices().indexOf(device) >= 0) { - mModulesWithDevicesNames.insert(module->getName()); - break; - } - } - } - } - } - status_t getStatus() const { return mStatus; } - std::string getError() const { - if (mFilePath.empty()) { - return std::string{"Could not find "} + kConfigFileName + - " file in: " + testing::PrintToString(android::audio_get_configuration_paths()); - } else { - return "Invalid config file: " + mFilePath; - } - } - const std::string& getFilePath() const { return mFilePath; } - sp getModuleFromName(const std::string& name) const { - return getHwModules().getModuleFromName(name.c_str()); - } - sp getPrimaryModule() const { return mPrimaryModule; } - const std::set& getModulesWithDevicesNames() const { - return mModulesWithDevicesNames; - } - - private: - status_t mStatus = NO_INIT; - std::string mFilePath; - sp mPrimaryModule = nullptr; - std::set mModulesWithDevicesNames; -}; +static constexpr char kConfigFileName[] = "audio_policy_configuration.xml"; // Cached policy config after parsing for faster test startup const PolicyConfig& getCachedPolicyConfig() { static std::unique_ptr policyConfig = [] { - auto config = std::make_unique(); + auto config = std::make_unique(kConfigFileName); return config; }(); return *policyConfig; @@ -449,9 +387,10 @@ class AccessorHidlTest : public BaseTestClass { * The getter and/or the setter may return NOT_SUPPORTED if optionality == OPTIONAL. */ template - void testAccessors(IUTGetter iutGetter, const string& propertyName, - const Initial expectedInitial, list valuesToTest, Setter setter, - Getter getter, const vector& invalidValues = {}) { + void testAccessors(IUTGetter iutGetter, const std::string& propertyName, + const Initial expectedInitial, std::list valuesToTest, + Setter setter, Getter getter, + const std::vector& invalidValues = {}) { const auto expectedResults = {Result::OK, optionality == OPTIONAL ? Result::NOT_SUPPORTED : Result::OK}; @@ -495,9 +434,9 @@ class AccessorHidlTest : public BaseTestClass { EXPECT_RESULT(expectedResults, ((this->*iutGetter)().get()->*setter)(initialValue)); } template - void testAccessors(const string& propertyName, const Initial expectedInitial, - list valuesToTest, Setter setter, Getter getter, - const vector& invalidValues = {}) { + void testAccessors(const std::string& propertyName, const Initial expectedInitial, + std::list valuesToTest, Setter setter, Getter getter, + const std::vector& invalidValues = {}) { testAccessors(&BaseTestClass::getDevice, propertyName, expectedInitial, valuesToTest, setter, getter, invalidValues); } @@ -573,9 +512,13 @@ GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioPatchHidlTest); // Nesting a tuple in another tuple allows to use GTest Combine function to generate // all combinations of devices and configs. enum { PARAM_DEVICE, PARAM_CONFIG, PARAM_FLAGS }; +#if MAJOR_VERSION <= 6 enum { INDEX_INPUT, INDEX_OUTPUT }; using DeviceConfigParameter = std::tuple>; +#elif MAJOR_VERSION >= 7 +using DeviceConfigParameter = std::tuple>; +#endif #if MAJOR_VERSION >= 6 const std::vector& getInputDeviceConfigParameters(); @@ -583,8 +526,8 @@ const std::vector& getOutputDeviceConfigParameters(); #endif #if MAJOR_VERSION >= 4 -static string SanitizeStringForGTestName(const string& s) { - string result = s; +static std::string SanitizeStringForGTestName(const std::string& s) { + std::string result = s; for (size_t i = 0; i < result.size(); i++) { // gtest test names must only contain alphanumeric characters if (!std::isalnum(result[i])) result[i] = '_'; @@ -598,43 +541,57 @@ static string SanitizeStringForGTestName(const string& s) { * As the only parameter changing are channel mask and sample rate, * only print those ones in the test name. */ -static string DeviceConfigParameterToString( +static std::string DeviceConfigParameterToString( const testing::TestParamInfo& info) { const AudioConfig& config = std::get(info.param); const auto deviceName = DeviceParameterToString(::testing::TestParamInfo{ std::get(info.param), info.index}); - return (deviceName.empty() ? "" : deviceName + "_") + to_string(info.index) + "__" + - to_string(config.sampleRateHz) + "_" + - // "MONO" is more clear than "FRONT_LEFT" - ((config.channelMask == mkEnumBitfield(AudioChannelMask::OUT_MONO) || - config.channelMask == mkEnumBitfield(AudioChannelMask::IN_MONO)) - ? "MONO" + const auto devicePart = + (deviceName.empty() ? "" : deviceName + "_") + std::to_string(info.index); + // The types had changed a lot between versions 2, 4..6 and 7. Use separate + // code sections for easier understanding. #if MAJOR_VERSION == 2 - : ::testing::PrintToString(config.channelMask) -#elif MAJOR_VERSION >= 4 - // In V4 and above the channel mask is a bitfield. - // Printing its value using HIDL's toString for a bitfield emits a lot of extra - // text due to overlapping constant values. Instead, we print the bitfield value - // as if it was a single value + its hex representation - : SanitizeStringForGTestName( - ::testing::PrintToString(AudioChannelMask(config.channelMask)) + "_" + - toHexString(config.channelMask)) -#endif - ) + - "_" + -#if MAJOR_VERSION == 2 - std::visit([](auto&& arg) -> std::string { return ::testing::PrintToString(arg); }, - std::get(info.param)); -#elif MAJOR_VERSION >= 4 - SanitizeStringForGTestName(std::visit( - [](auto&& arg) -> std::string { - using T = std::decay_t; - // Need to use FQN of toString to avoid confusing the compiler - return ::android::hardware::audio::common::CPP_VERSION::toString( - hidl_bitfield(arg)); - }, - std::get(info.param))); + const auto configPart = + std::to_string(config.sampleRateHz) + "_" + + // "MONO" is more clear than "FRONT_LEFT" + (config.channelMask == AudioChannelMask::OUT_MONO || + config.channelMask == AudioChannelMask::IN_MONO + ? "MONO" + : ::testing::PrintToString(config.channelMask)) + + "_" + + std::visit([](auto&& arg) -> std::string { return ::testing::PrintToString(arg); }, + std::get(info.param)); +#elif MAJOR_VERSION >= 4 && MAJOR_VERSION <= 6 + const auto configPart = + std::to_string(config.sampleRateHz) + "_" + + // "MONO" is more clear than "FRONT_LEFT" + (config.channelMask == mkEnumBitfield(AudioChannelMask::OUT_MONO) || + config.channelMask == mkEnumBitfield(AudioChannelMask::IN_MONO) + ? "MONO" + // In V4 and above the channel mask is a bitfield. + // Printing its value using HIDL's toString for a bitfield emits a lot of extra + // text due to overlapping constant values. Instead, we print the bitfield + // value as if it was a single value + its hex representation + : SanitizeStringForGTestName( + ::testing::PrintToString(AudioChannelMask(config.channelMask)) + + "_" + toHexString(config.channelMask))) + + "_" + + SanitizeStringForGTestName(std::visit( + [](auto&& arg) -> std::string { + using T = std::decay_t; + // Need to use FQN of toString to avoid confusing the compiler + return ::android::hardware::audio::common::CPP_VERSION::toString( + hidl_bitfield(arg)); + }, + std::get(info.param))); +#elif MAJOR_VERSION >= 7 + const auto configPart = + std::to_string(config.base.sampleRateHz) + "_" + + // The channel masks and flags are vectors of strings, just need to sanitize them. + SanitizeStringForGTestName(::testing::PrintToString(config.base.channelMask)) + "_" + + SanitizeStringForGTestName(::testing::PrintToString(std::get(info.param))); #endif + return devicePart + "__" + configPart; } class AudioHidlTestWithDeviceConfigParameter @@ -660,7 +617,7 @@ class AudioHidlTestWithDeviceConfigParameter AudioOutputFlag getOutputFlags() const { return std::get(std::get(GetParam())); } -#elif MAJOR_VERSION >= 4 +#elif MAJOR_VERSION >= 4 && MAJOR_VERSION <= 6 hidl_bitfield getInputFlags() const { return hidl_bitfield( std::get(std::get(GetParam()))); @@ -669,10 +626,17 @@ class AudioHidlTestWithDeviceConfigParameter return hidl_bitfield( std::get(std::get(GetParam()))); } +#elif MAJOR_VERSION >= 7 + hidl_vec getInputFlags() const { return std::get(GetParam()); } + hidl_vec getOutputFlags() const { return std::get(GetParam()); } #endif }; +#if MAJOR_VERSION <= 6 +#define AUDIO_PRIMARY_HIDL_HAL_TEST #include "ConfigHelper.h" +#undef AUDIO_PRIMARY_HIDL_HAL_TEST +#endif ////////////////////////////////////////////////////////////////////////////// ///////////////////////////// getInputBufferSize ///////////////////////////// @@ -839,7 +803,7 @@ class StreamHelper { AudioConfig* suggestedConfigPtr) { // FIXME: Open a stream without an IOHandle // This is not required to be accepted by hal implementations - AudioIoHandle ioHandle = (AudioIoHandle)AudioHandleConsts::AUDIO_IO_HANDLE_NONE; + AudioIoHandle ioHandle{}; AudioConfig suggestedConfig{}; bool retryWithSuggestedConfig = true; if (suggestedConfigPtr == nullptr) { @@ -932,7 +896,11 @@ class OpenStreamTest : public AudioHidlTestWithDeviceConfigParameter { class OutputStreamTest : public OpenStreamTest { void SetUp() override { ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp()); // setup base +#if MAJOR_VERSION <= 6 address.device = AudioDevice::OUT_DEFAULT; +#elif MAJOR_VERSION >= 7 + address.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_DEFAULT); +#endif const AudioConfig& config = getConfig(); auto flags = getOutputFlags(); testOpen( @@ -946,13 +914,19 @@ class OutputStreamTest : public OpenStreamTest { }, config); } -#if MAJOR_VERSION >= 4 +#if MAJOR_VERSION >= 4 && MAJOR_VERSION <= 6 - protected: + protected: const SourceMetadata initMetadata = { { { AudioUsage::MEDIA, AudioContentType::MUSIC, 1 /* gain */ } }}; +#elif MAJOR_VERSION >= 7 + protected: + const SourceMetadata initMetadata = { + { { toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA), + toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_MUSIC), + 1 /* gain */ } }}; #endif }; TEST_P(OutputStreamTest, OpenOutputStreamTest) { @@ -995,7 +969,11 @@ GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(OutputStreamTest); class InputStreamTest : public OpenStreamTest { void SetUp() override { ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp()); // setup base +#if MAJOR_VERSION <= 6 address.device = AudioDevice::IN_DEFAULT; +#elif MAJOR_VERSION <= 7 + address.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_IN_DEFAULT); +#endif const AudioConfig& config = getConfig(); auto flags = getInputFlags(); testOpen( @@ -1009,8 +987,11 @@ class InputStreamTest : public OpenStreamTest { protected: #if MAJOR_VERSION == 2 const AudioSource initMetadata = AudioSource::DEFAULT; -#elif MAJOR_VERSION >= 4 - const SinkMetadata initMetadata = {{{.source = AudioSource::DEFAULT, .gain = 1}}}; +#elif MAJOR_VERSION >= 4 && MAJOR_VERSION <= 6 + const SinkMetadata initMetadata = {{ {.source = AudioSource::DEFAULT, .gain = 1 } }}; +#elif MAJOR_VERSION >= 7 + const SinkMetadata initMetadata = { + {{.source = toString(xsd::AudioSource::AUDIO_SOURCE_DEFAULT), .gain = 1}}}; #endif }; @@ -1067,6 +1048,7 @@ GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(InputStreamTest); TEST_IO_STREAM(GetFrameCount, "Check that getting stream frame count does not crash the HAL.", ASSERT_TRUE(stream->getFrameCount().isOk())) +#if MAJOR_VERSION <= 6 TEST_IO_STREAM(GetSampleRate, "Check that the stream sample rate == the one it was opened with", ASSERT_EQ(audioConfig.sampleRateHz, extract(stream->getSampleRate()))) @@ -1075,6 +1057,7 @@ TEST_IO_STREAM(GetChannelMask, "Check that the stream channel mask == the one it TEST_IO_STREAM(GetFormat, "Check that the stream format == the one it was opened with", ASSERT_EQ(audioConfig.format, extract(stream->getFormat()))) +#endif // TODO: for now only check that the framesize is not incoherent TEST_IO_STREAM(GetFrameSize, "Check that the stream frame size == the one it was opened with", @@ -1084,7 +1067,7 @@ TEST_IO_STREAM(GetBufferSize, "Check that the stream buffer size== the one it wa ASSERT_GE(extract(stream->getBufferSize()), extract(stream->getFrameSize()))); template -static void testCapabilityGetter(const string& name, IStream* stream, +static void testCapabilityGetter(const std::string& name, IStream* stream, CapabilityGetter capabilityGetter, Return (IStream::*getter)(), Return (IStream::*setter)(Property), @@ -1120,6 +1103,7 @@ static void testCapabilityGetter(const string& name, IStream* stream, } } +#if MAJOR_VERSION <= 6 TEST_IO_STREAM(SupportedSampleRate, "Check that the stream sample rate is declared as supported", testCapabilityGetter("getSupportedSampleRate", stream.get(), &GetSupported::sampleRates, &IStream::getSampleRate, @@ -1137,19 +1121,71 @@ TEST_IO_STREAM(SupportedChannelMask, "Check that the stream channel mask is decl TEST_IO_STREAM(SupportedFormat, "Check that the stream format is declared as supported", testCapabilityGetter("getSupportedFormat", stream.get(), &GetSupported::formats, &IStream::getFormat, &IStream::setFormat)) +#else +static void testGetSupportedProfiles(IStream* stream) { + Result res; + hidl_vec profiles; + auto ret = stream->getSupportedProfiles(returnIn(res, profiles)); + EXPECT_TRUE(ret.isOk()); + if (res == Result::OK) { + EXPECT_GT(profiles.size(), 0); + } else { + EXPECT_EQ(Result::NOT_SUPPORTED, res); + } +} + +TEST_IO_STREAM(GetSupportedProfiles, "Try to call optional method GetSupportedProfiles", + testGetSupportedProfiles(stream.get())) + +static void testSetAudioProperties(IStream* stream) { + Result res; + hidl_vec profiles; + auto ret = stream->getSupportedProfiles(returnIn(res, profiles)); + EXPECT_TRUE(ret.isOk()); + if (res == Result::NOT_SUPPORTED) { + GTEST_SKIP() << "Retrieving supported profiles is not implemented"; + } + for (const auto& profile : profiles) { + for (const auto& sampleRate : profile.sampleRates) { + for (const auto& channelMask : profile.channelMasks) { + AudioConfigBase config{.format = profile.format, + .sampleRateHz = sampleRate, + .channelMask = channelMask}; + auto ret = stream->setAudioProperties(config); + EXPECT_TRUE(ret.isOk()); + EXPECT_EQ(Result::OK, ret) << config.format << "; " << config.sampleRateHz << "; " + << toString(config.channelMask); + } + } + } +} + +TEST_IO_STREAM(SetAudioProperties, "Call setAudioProperties for all supported profiles", + testSetAudioProperties(stream.get())) +#endif static void testGetAudioProperties(IStream* stream, AudioConfig expectedConfig) { +#if MAJOR_VERSION <= 6 uint32_t sampleRateHz; auto mask = mkEnumBitfield({}); AudioFormat format; - stream->getAudioProperties(returnIn(sampleRateHz, mask, format)); + auto ret = stream->getAudioProperties(returnIn(sampleRateHz, mask, format)); + EXPECT_TRUE(ret.isOk()); // FIXME: the qcom hal it does not currently negotiate the sampleRate & // channel mask EXPECT_EQ(expectedConfig.sampleRateHz, sampleRateHz); EXPECT_EQ(expectedConfig.channelMask, mask); EXPECT_EQ(expectedConfig.format, format); +#elif MAJOR_VERSION >= 7 + AudioConfigBase actualConfig{}; + auto ret = stream->getAudioProperties(returnIn(actualConfig)); + EXPECT_TRUE(ret.isOk()); + EXPECT_EQ(expectedConfig.base.sampleRateHz, actualConfig.sampleRateHz); + EXPECT_EQ(expectedConfig.base.channelMask, actualConfig.channelMask); + EXPECT_EQ(expectedConfig.base.format, actualConfig.format); +#endif } TEST_IO_STREAM(GetAudioProperties, @@ -1160,7 +1196,7 @@ TEST_IO_STREAM(SetHwAvSync, "Try to set hardware sync to an invalid value", ASSERT_RESULT(okOrNotSupportedOrInvalidArgs, stream->setHwAvSync(666))) static void checkGetNoParameter(IStream* stream, hidl_vec keys, - initializer_list expectedResults) { + std::initializer_list expectedResults) { hidl_vec parameters; Result res; ASSERT_OK(Parameters::get(stream, keys, returnIn(res, parameters))); @@ -1271,7 +1307,11 @@ TEST_P(InputStreamTest, GetAudioSource) { return; } ASSERT_OK(res); +#if MAJOR_VERSION <= 6 ASSERT_EQ(AudioSource::DEFAULT, source); +#elif MAJOR_VERSION >= 7 + ASSERT_EQ(xsd::AudioSource::AUDIO_SOURCE_DEFAULT, xsd::stringToAudioSource(source)); +#endif } static void testUnitaryGain(std::function(float)> setGain) { @@ -1286,7 +1326,7 @@ static void testUnitaryGain(std::function(float)> setGain) { } static void testOptionalUnitaryGain(std::function(float)> setGain, - string debugName) { + std::string debugName) { auto result = setGain(1); ASSERT_IS_OK(result); if (result == Result::NOT_SUPPORTED) { @@ -1306,7 +1346,7 @@ static void testPrepareForReading(IStreamIn* stream, uint32_t frameSize, uint32_ Result res; // Ignore output parameters as the call should fail ASSERT_OK(stream->prepareForReading(frameSize, framesCount, - [&res](auto r, auto&, auto&, auto&, auto&) { res = r; })); + [&res](auto r, auto&, auto&, auto&, auto) { res = r; })); EXPECT_RESULT(Result::INVALID_ARGUMENTS, res); } @@ -1371,7 +1411,7 @@ static void testPrepareForWriting(IStreamOut* stream, uint32_t frameSize, uint32 Result res; // Ignore output parameters as the call should fail ASSERT_OK(stream->prepareForWriting(frameSize, framesCount, - [&res](auto r, auto&, auto&, auto&, auto&) { res = r; })); + [&res](auto r, auto&, auto&, auto&, auto) { res = r; })); EXPECT_RESULT(Result::INVALID_ARGUMENTS, res); } diff --git a/audio/core/all-versions/vts/functional/ConfigHelper.h b/audio/core/all-versions/vts/functional/ConfigHelper.h index 8ef2b436bb..1a1dbea939 100644 --- a/audio/core/all-versions/vts/functional/ConfigHelper.h +++ b/audio/core/all-versions/vts/functional/ConfigHelper.h @@ -14,6 +14,8 @@ * limitations under the License. */ +#pragma once + // Code in this file uses 'getCachedPolicyConfig' #ifndef AUDIO_PRIMARY_HIDL_HAL_TEST #error Must be included from AudioPrimaryHidlTest.h @@ -46,32 +48,32 @@ struct ConfigHelper { } // Cache result ? - static const vector getRequiredSupportPlaybackAudioConfig() { + static const std::vector getRequiredSupportPlaybackAudioConfig() { return combineAudioConfig({AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO}, {8000, 11025, 16000, 22050, 32000, 44100}, {AudioFormat::PCM_16_BIT}); } - static const vector getRecommendedSupportPlaybackAudioConfig() { + static const std::vector getRecommendedSupportPlaybackAudioConfig() { return combineAudioConfig({AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO}, {24000, 48000}, {AudioFormat::PCM_16_BIT}); } - static const vector getRequiredSupportCaptureAudioConfig() { + static const std::vector getRequiredSupportCaptureAudioConfig() { if (!primaryHasMic()) return {}; return combineAudioConfig({AudioChannelMask::IN_MONO}, {8000, 11025, 16000, 44100}, {AudioFormat::PCM_16_BIT}); } - static const vector getRecommendedSupportCaptureAudioConfig() { + static const std::vector getRecommendedSupportCaptureAudioConfig() { if (!primaryHasMic()) return {}; return combineAudioConfig({AudioChannelMask::IN_STEREO}, {22050, 48000}, {AudioFormat::PCM_16_BIT}); } - static vector combineAudioConfig(vector channelMasks, - vector sampleRates, - audio_format_t format) { - vector configs; + static std::vector combineAudioConfig( + std::vector channelMasks, std::vector sampleRates, + audio_format_t format) { + std::vector configs; configs.reserve(channelMasks.size() * sampleRates.size()); for (auto channelMask : channelMasks) { for (auto sampleRate : sampleRates) { @@ -86,10 +88,10 @@ struct ConfigHelper { return configs; } - static vector combineAudioConfig(vector channelMasks, - vector sampleRates, - vector formats) { - vector configs; + static std::vector combineAudioConfig(std::vector channelMasks, + std::vector sampleRates, + std::vector formats) { + std::vector configs; configs.reserve(channelMasks.size() * sampleRates.size() * formats.size()); for (auto channelMask : channelMasks) { for (auto sampleRate : sampleRates) { diff --git a/audio/core/all-versions/vts/functional/DeviceManager.h b/audio/core/all-versions/vts/functional/DeviceManager.h index 0c0727f283..6efed7991e 100644 --- a/audio/core/all-versions/vts/functional/DeviceManager.h +++ b/audio/core/all-versions/vts/functional/DeviceManager.h @@ -14,10 +14,11 @@ * limitations under the License. */ -// Code in this file uses 'environment' -#ifndef AUDIO_PRIMARY_HIDL_HAL_TEST -#error Must be included from AudioPrimaryHidlTest.h -#endif +#pragma once + +// Note: it is assumed that this file is included from AudioPrimaryHidlTest.h +// and thus it doesn't have all '#include' and 'using' directives required +// for a standalone compilation. template class InterfaceManager { diff --git a/audio/core/all-versions/vts/functional/PolicyConfig.h b/audio/core/all-versions/vts/functional/PolicyConfig.h new file mode 100644 index 0000000000..c9e0c0dd5a --- /dev/null +++ b/audio/core/all-versions/vts/functional/PolicyConfig.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2020 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. + */ + +#pragma once + +// Note: it is assumed that this file is included from AudioPrimaryHidlTest.h +// and thus it doesn't have all '#include' and 'using' directives required +// for a standalone compilation. + +#include + +struct PolicyConfigData { + android::HwModuleCollection hwModules; + android::DeviceVector availableOutputDevices; + android::DeviceVector availableInputDevices; + sp defaultOutputDevice; +}; + +class PolicyConfig : private PolicyConfigData, public android::AudioPolicyConfig { + public: + explicit PolicyConfig(const std::string& configFileName) + : android::AudioPolicyConfig(hwModules, availableOutputDevices, availableInputDevices, + defaultOutputDevice), + mConfigFileName{configFileName} { + for (const auto& location : android::audio_get_configuration_paths()) { + std::string path = location + '/' + mConfigFileName; + if (access(path.c_str(), F_OK) == 0) { + mFilePath = path; + break; + } + } + mStatus = android::deserializeAudioPolicyFile(mFilePath.c_str(), this); + if (mStatus == OK) { + mPrimaryModule = getModuleFromName(DeviceManager::kPrimaryDevice); + // Available devices are not 'attached' to modules at this moment. + // Need to go over available devices and find their module. + for (const auto& device : availableOutputDevices) { + for (const auto& module : hwModules) { + if (module->getDeclaredDevices().indexOf(device) >= 0) { + mModulesWithDevicesNames.insert(module->getName()); + break; + } + } + } + for (const auto& device : availableInputDevices) { + for (const auto& module : hwModules) { + if (module->getDeclaredDevices().indexOf(device) >= 0) { + mModulesWithDevicesNames.insert(module->getName()); + break; + } + } + } + } + } + status_t getStatus() const { return mStatus; } + std::string getError() const { + if (mFilePath.empty()) { + return std::string{"Could not find "} + mConfigFileName + + " file in: " + testing::PrintToString(android::audio_get_configuration_paths()); + } else { + return "Invalid config file: " + mFilePath; + } + } + const std::string& getFilePath() const { return mFilePath; } + sp getModuleFromName(const std::string& name) const { + return getHwModules().getModuleFromName(name.c_str()); + } + sp getPrimaryModule() const { return mPrimaryModule; } + const std::set& getModulesWithDevicesNames() const { + return mModulesWithDevicesNames; + } + bool haveInputProfilesInModule(const std::string& name) const { + auto module = getModuleFromName(name); + return module && !module->getInputProfiles().empty(); + } + + private: + const std::string mConfigFileName; + status_t mStatus = NO_INIT; + std::string mFilePath; + sp mPrimaryModule = nullptr; + std::set mModulesWithDevicesNames; +}; diff --git a/audio/effect/all-versions/vts/functional/Android.bp b/audio/effect/all-versions/vts/functional/Android.bp index 7cdb18f95f..f4a72834d5 100644 --- a/audio/effect/all-versions/vts/functional/Android.bp +++ b/audio/effect/all-versions/vts/functional/Android.bp @@ -118,7 +118,6 @@ cc_test { } cc_test { - enabled: false, name: "VtsHalAudioEffectV7_0TargetTest", defaults: ["VtsHalAudioEffectTargetTest_default"], // Use test_config for vts suite. @@ -126,6 +125,7 @@ cc_test { test_config: "VtsHalAudioEffectV7_0TargetTest.xml", static_libs: [ "android.hardware.audio.common@7.0", + "android.hardware.audio.common@7.0-enums", "android.hardware.audio.effect@7.0", ], data: [ diff --git a/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp b/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp index 4787c091b2..b64f105eb4 100644 --- a/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp +++ b/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp @@ -16,7 +16,9 @@ #define LOG_TAG "AudioEffectHidlHalTest" #include +#if MAJOR_VERSION <= 6 #include +#endif #include PATH(android/hardware/audio/effect/FILE_VERSION/IEffect.h) #include PATH(android/hardware/audio/effect/FILE_VERSION/IEffectsFactory.h) @@ -25,6 +27,10 @@ #include PATH(android/hardware/audio/effect/FILE_VERSION/types.h) #include #include +#if MAJOR_VERSION >= 7 +#include +#include +#endif #include @@ -45,6 +51,12 @@ using ::android::hidl::allocator::V1_0::IAllocator; using ::android::hidl::memory::V1_0::IMemory; using namespace ::android::hardware::audio::common::CPP_VERSION; using namespace ::android::hardware::audio::effect::CPP_VERSION; +#if MAJOR_VERSION >= 7 +// Make an alias for enumerations generated from the APM config XSD. +namespace xsd { +using namespace ::audio::policy::configuration::CPP_VERSION; +} +#endif #ifndef ARRAY_SIZE #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a))) @@ -171,7 +183,7 @@ class AudioEffectHidlTest : public ::testing::TestWithParam { effectsFactory = IEffectsFactory::getService(std::get(GetParam())); ASSERT_NE(nullptr, effectsFactory.get()); - findAndCreateEffect(getEffectType()); + ASSERT_NO_FATAL_FAILURE(findAndCreateEffect(getEffectType())); ASSERT_NE(nullptr, effect.get()); Return ret = effect->init(); @@ -201,7 +213,7 @@ class AudioEffectHidlTest : public ::testing::TestWithParam { void AudioEffectHidlTest::findAndCreateEffect(const Uuid& type) { Uuid effectUuid; - findEffectInstance(type, &effectUuid); + ASSERT_NO_FATAL_FAILURE(findEffectInstance(type, &effectUuid)); Return ret = effectsFactory->createEffect( effectUuid, 1 /*session*/, 1 /*ioHandle*/, #if MAJOR_VERSION >= 6 @@ -244,10 +256,16 @@ void AudioEffectHidlTest::getChannelCount(uint32_t* channelCount) { }); ASSERT_TRUE(ret.isOk()); ASSERT_EQ(Result::OK, retval); +#if MAJOR_VERSION <= 6 ASSERT_TRUE(audio_channel_mask_is_valid( static_cast(currentConfig.outputCfg.channels))); *channelCount = audio_channel_count_from_out_mask( static_cast(currentConfig.outputCfg.channels)); +#else + *channelCount = + audio::policy::configuration::V7_0::getChannelCount(currentConfig.outputCfg.channels); + ASSERT_NE(*channelCount, 0); +#endif } TEST_P(AudioEffectHidlTest, Close) { @@ -391,7 +409,12 @@ TEST_P(AudioEffectHidlTest, DisableEnableDisable) { TEST_P(AudioEffectHidlTest, SetDevice) { description("Verify that SetDevice works for an output chain effect"); +#if MAJOR_VERSION <= 6 Return ret = effect->setDevice(mkEnumBitfield(AudioDevice::OUT_SPEAKER)); +#else + DeviceAddress device{.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_SPEAKER)}; + Return ret = effect->setDevice(device); +#endif EXPECT_TRUE(ret.isOk()); EXPECT_EQ(Result::OK, ret); } @@ -441,22 +464,28 @@ TEST_P(AudioEffectHidlTest, SetConfigReverse) { TEST_P(AudioEffectHidlTest, SetInputDevice) { description("Verify that SetInputDevice does not crash"); +#if MAJOR_VERSION <= 6 Return ret = effect->setInputDevice(mkEnumBitfield(AudioDevice::IN_BUILTIN_MIC)); +#else + DeviceAddress device{.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_IN_BUILTIN_MIC)}; + Return ret = effect->setInputDevice(device); +#endif EXPECT_TRUE(ret.isOk()); } TEST_P(AudioEffectHidlTest, SetAudioSource) { description("Verify that SetAudioSource does not crash"); +#if MAJOR_VERSION <= 6 Return ret = effect->setAudioSource(AudioSource::MIC); +#else + Return ret = effect->setAudioSource(toString(xsd::AudioSource::AUDIO_SOURCE_MIC)); +#endif EXPECT_TRUE(ret.isOk()); } TEST_P(AudioEffectHidlTest, Offload) { description("Verify that calling Offload method does not crash"); - EffectOffloadParameter offloadParam; - offloadParam.isOffload = false; - offloadParam.ioHandle = static_cast(AudioHandleConsts::AUDIO_IO_HANDLE_NONE); - Return ret = effect->offload(offloadParam); + Return ret = effect->offload(EffectOffloadParameter{}); EXPECT_TRUE(ret.isOk()); }