Merge changes from topic "nullzero-hal-v7"

* changes:
  Remove PREUPLOAD.cfg from audio HAL example
  audio: Implement VTS tests for V7.0
  audio: Add example HAL implementation
  audio: Reformat README as Markdown
  audio: HAL V7 tweaks
This commit is contained in:
Treehugger Robot 2020-11-23 19:25:49 +00:00 committed by Gerrit Code Review
commit 8d93e3a8d3
39 changed files with 2151 additions and 340 deletions

View file

@ -117,7 +117,7 @@ interface IDevice {
AudioIoHandle ioHandle,
DeviceAddress device,
AudioConfig config,
bitfield<AudioOutputFlag> flags,
vec<AudioInOutFlag> flags,
SourceMetadata sourceMetadata) generates (
Result retval,
IStreamOut outStream,
@ -142,7 +142,7 @@ interface IDevice {
AudioIoHandle ioHandle,
DeviceAddress device,
AudioConfig config,
bitfield<AudioInputFlag> flags,
vec<AudioInOutFlag> flags,
SinkMetadata sinkMetadata) generates (
Result retval,
IStreamIn inStream,

View file

@ -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<uint32_t> 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<vec<AudioChannelMask>> 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<AudioFormat> formats);
getSupportedProfiles()
generates (Result retval, vec<AudioProfile> 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.

View file

@ -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<audio.policy.configuration.V7_0.AudioInOutFlag> 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<audio.policy.configuration.V7_0.AudioUsage> getPreferredUsage();
method public java.util.List<audio.policy.configuration.V7_0.Profile> getProfile();
method public audio.policy.configuration.V7_0.Role getRole();
method public void setFlags(String);
method public void setFlags(java.util.List<audio.policy.configuration.V7_0.AudioInOutFlag>);
method public void setGains(audio.policy.configuration.V7_0.Gains);
method public void setMaxActiveCount(long);
method public void setMaxOpenCount(long);

View file

@ -155,16 +155,41 @@
<xs:element name="item" type="xs:token" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="audioInOutFlags">
<xs:simpleType name="audioInOutFlag">
<xs:annotation>
<xs:documentation xml:lang="en">
"|" separated list of audio_output_flags_t or audio_input_flags_t.
The flags indicate suggested stream attributes supported by the profile.
</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:pattern value="|[_A-Z]+(\|[_A-Z]+)*"/>
<xs:enumeration value="AUDIO_OUTPUT_FLAG_DIRECT" />
<xs:enumeration value="AUDIO_OUTPUT_FLAG_PRIMARY" />
<xs:enumeration value="AUDIO_OUTPUT_FLAG_FAST" />
<xs:enumeration value="AUDIO_OUTPUT_FLAG_DEEP_BUFFER" />
<xs:enumeration value="AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD" />
<xs:enumeration value="AUDIO_OUTPUT_FLAG_NON_BLOCKING" />
<xs:enumeration value="AUDIO_OUTPUT_FLAG_HW_AV_SYNC" />
<xs:enumeration value="AUDIO_OUTPUT_FLAG_TTS" />
<xs:enumeration value="AUDIO_OUTPUT_FLAG_RAW" />
<xs:enumeration value="AUDIO_OUTPUT_FLAG_SYNC" />
<xs:enumeration value="AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO" />
<xs:enumeration value="AUDIO_OUTPUT_FLAG_DIRECT_PCM" />
<xs:enumeration value="AUDIO_OUTPUT_FLAG_MMAP_NOIRQ" />
<xs:enumeration value="AUDIO_OUTPUT_FLAG_VOIP_RX" />
<xs:enumeration value="AUDIO_OUTPUT_FLAG_INCALL_MUSIC" />
<xs:enumeration value="AUDIO_INPUT_FLAG_FAST" />
<xs:enumeration value="AUDIO_INPUT_FLAG_HW_HOTWORD" />
<xs:enumeration value="AUDIO_INPUT_FLAG_RAW" />
<xs:enumeration value="AUDIO_INPUT_FLAG_SYNC" />
<xs:enumeration value="AUDIO_INPUT_FLAG_MMAP_NOIRQ" />
<xs:enumeration value="AUDIO_INPUT_FLAG_VOIP_TX" />
<xs:enumeration value="AUDIO_INPUT_FLAG_HW_AV_SYNC" />
<xs:enumeration value="AUDIO_INPUT_FLAG_DIRECT" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="audioInOutFlags">
<xs:list itemType="audioInOutFlag" />
</xs:simpleType>
<xs:simpleType name="role">
<xs:restriction base="xs:string">
<xs:enumeration value="sink"/>

View file

@ -128,6 +128,7 @@ updateFile() {
for F in $SOURCE_FILES; do
updateFile ${F} "channelMasks" ","
updateFile ${F} "samplingRates" ","
updateFile ${F} "flags" "|"
done;
updateIncludes() {

View file

@ -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;

View file

@ -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

53
audio/README.md Normal file
View file

@ -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.

View file

@ -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",

View file

@ -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 <sys/types.h>
#include <audio_policy_configuration_V7_0.h>
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

View file

@ -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",
],
}

View file

@ -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 <log/log.h>
#include "DevicesFactory.h"
using ::android::hardware::hidl_string;
using ::android::hardware::Return;
using ::android::hardware::Void;
namespace android::hardware::audio::V7_0::implementation {
Return<void> DevicesFactory::openDevice(const hidl_string& device, openDevice_cb _hidl_cb) {
(void)device;
_hidl_cb(Result::INVALID_ARGUMENTS, nullptr);
return Void();
}
Return<void> DevicesFactory::openPrimaryDevice(openPrimaryDevice_cb _hidl_cb) {
_hidl_cb(Result::INVALID_ARGUMENTS, nullptr);
return Void();
}
} // namespace android::hardware::audio::V7_0::implementation

View file

@ -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 <android/hardware/audio/7.0/IDevicesFactory.h>
namespace android::hardware::audio::V7_0::implementation {
class DevicesFactory : public IDevicesFactory {
public:
DevicesFactory() = default;
::android::hardware::Return<void> openDevice(const ::android::hardware::hidl_string& device,
openDevice_cb _hidl_cb) override;
::android::hardware::Return<void> openPrimaryDevice(openPrimaryDevice_cb _hidl_cb) override;
};
} // namespace android::hardware::audio::V7_0::implementation

View file

@ -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 <log/log.h>
#include <audio_policy_configuration_V7_0.h>
#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<Result> Effect::init() {
return Result::OK;
}
Return<Result> Effect::setConfig(
const EffectConfig& config,
const ::android::sp<IEffectBufferProviderCallback>& inputBufferProvider,
const ::android::sp<IEffectBufferProviderCallback>& outputBufferProvider) {
(void)config;
(void)inputBufferProvider;
(void)outputBufferProvider;
return Result::OK;
}
Return<Result> Effect::reset() {
return Result::OK;
}
Return<Result> Effect::enable() {
if (!mEnabled) {
mEnabled = true;
return Result::OK;
} else {
return Result::NOT_SUPPORTED;
}
}
Return<Result> Effect::disable() {
if (mEnabled) {
mEnabled = false;
return Result::OK;
} else {
return Result::NOT_SUPPORTED;
}
}
Return<Result> Effect::setDevice(const DeviceAddress& device) {
(void)device;
return Result::OK;
}
Return<void> Effect::setAndGetVolume(const hidl_vec<uint32_t>& volumes,
setAndGetVolume_cb _hidl_cb) {
(void)volumes;
_hidl_cb(Result::OK, hidl_vec<uint32_t>{});
return Void();
}
Return<Result> Effect::volumeChangeNotification(const hidl_vec<uint32_t>& volumes) {
(void)volumes;
return Result::OK;
}
Return<Result> Effect::setAudioMode(AudioMode mode) {
(void)mode;
return Result::OK;
}
Return<Result> Effect::setConfigReverse(
const EffectConfig& config,
const ::android::sp<IEffectBufferProviderCallback>& inputBufferProvider,
const ::android::sp<IEffectBufferProviderCallback>& outputBufferProvider) {
(void)config;
(void)inputBufferProvider;
(void)outputBufferProvider;
return Result::OK;
}
Return<Result> Effect::setInputDevice(const DeviceAddress& device) {
(void)device;
return Result::OK;
}
Return<void> 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<void> Effect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
_hidl_cb(Result::OK, EffectConfig{});
return Void();
}
Return<void> Effect::getSupportedAuxChannelsConfigs(uint32_t maxConfigs,
getSupportedAuxChannelsConfigs_cb _hidl_cb) {
(void)maxConfigs;
_hidl_cb(Result::OK, hidl_vec<EffectAuxChannelsConfig>{});
return Void();
}
Return<void> Effect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
_hidl_cb(Result::OK, EffectAuxChannelsConfig{});
return Void();
}
Return<Result> Effect::setAuxChannelsConfig(const EffectAuxChannelsConfig& config) {
(void)config;
return Result::OK;
}
Return<Result> Effect::setAudioSource(const hidl_string& source) {
(void)source;
return Result::OK;
}
Return<Result> Effect::offload(const EffectOffloadParameter& param) {
(void)param;
return Result::OK;
}
Return<void> Effect::getDescriptor(getDescriptor_cb _hidl_cb) {
_hidl_cb(Result::OK, mDescriptor);
return Void();
}
Return<void> Effect::prepareForProcessing(prepareForProcessing_cb _hidl_cb) {
_hidl_cb(Result::OK, MQDescriptor<Result, kSynchronizedReadWrite>{});
return Void();
}
Return<Result> Effect::setProcessBuffers(const AudioBuffer& inBuffer,
const AudioBuffer& outBuffer) {
(void)inBuffer;
(void)outBuffer;
return Result::OK;
}
Return<void> Effect::command(uint32_t commandId, const hidl_vec<uint8_t>& data,
uint32_t resultMaxSize, command_cb _hidl_cb) {
(void)commandId;
(void)data;
(void)resultMaxSize;
_hidl_cb(-EINVAL, hidl_vec<uint8_t>{});
return Void();
}
Return<Result> Effect::setParameter(const hidl_vec<uint8_t>& parameter,
const hidl_vec<uint8_t>& value) {
(void)parameter;
(void)value;
return Result::OK;
}
Return<void> Effect::getParameter(const hidl_vec<uint8_t>& parameter, uint32_t valueMaxSize,
getParameter_cb _hidl_cb) {
(void)parameter;
(void)valueMaxSize;
_hidl_cb(Result::OK, hidl_vec<uint8_t>{});
return Void();
}
Return<void> 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<uint8_t>{});
return Void();
}
Return<void> Effect::getCurrentConfigForFeature(uint32_t featureId, uint32_t configSize,
getCurrentConfigForFeature_cb _hidl_cb) {
(void)featureId;
(void)configSize;
_hidl_cb(Result::OK, hidl_vec<uint8_t>{});
return Void();
}
Return<Result> Effect::setCurrentConfigForFeature(uint32_t featureId,
const hidl_vec<uint8_t>& configData) {
(void)featureId;
(void)configData;
return Result::OK;
}
Return<Result> Effect::close() {
return Result::OK;
}
} // namespace android::hardware::audio::effect::V7_0::implementation

View file

@ -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 <android/hardware/audio/effect/7.0/IEffect.h>
namespace android::hardware::audio::effect::V7_0::implementation {
class Effect : public IEffect {
public:
explicit Effect(const EffectDescriptor& descriptor) : mDescriptor(descriptor) {}
::android::hardware::Return<Result> init() override;
::android::hardware::Return<Result> setConfig(
const EffectConfig& config,
const ::android::sp<IEffectBufferProviderCallback>& inputBufferProvider,
const ::android::sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
::android::hardware::Return<Result> reset() override;
::android::hardware::Return<Result> enable() override;
::android::hardware::Return<Result> disable() override;
::android::hardware::Return<Result> setDevice(
const ::android::hardware::audio::common::V7_0::DeviceAddress& device) override;
::android::hardware::Return<void> setAndGetVolume(
const ::android::hardware::hidl_vec<uint32_t>& volumes,
setAndGetVolume_cb _hidl_cb) override;
::android::hardware::Return<Result> volumeChangeNotification(
const ::android::hardware::hidl_vec<uint32_t>& volumes) override;
::android::hardware::Return<Result> setAudioMode(
::android::hardware::audio::common::V7_0::AudioMode mode) override;
::android::hardware::Return<Result> setConfigReverse(
const EffectConfig& config,
const ::android::sp<IEffectBufferProviderCallback>& inputBufferProvider,
const ::android::sp<IEffectBufferProviderCallback>& outputBufferProvider) override;
::android::hardware::Return<Result> setInputDevice(
const ::android::hardware::audio::common::V7_0::DeviceAddress& device) override;
::android::hardware::Return<void> getConfig(getConfig_cb _hidl_cb) override;
::android::hardware::Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb) override;
::android::hardware::Return<void> getSupportedAuxChannelsConfigs(
uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) override;
::android::hardware::Return<void> getAuxChannelsConfig(
getAuxChannelsConfig_cb _hidl_cb) override;
::android::hardware::Return<Result> setAuxChannelsConfig(
const EffectAuxChannelsConfig& config) override;
::android::hardware::Return<Result> setAudioSource(
const ::android::hardware::hidl_string& source) override;
::android::hardware::Return<Result> offload(const EffectOffloadParameter& param) override;
::android::hardware::Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override;
::android::hardware::Return<void> prepareForProcessing(
prepareForProcessing_cb _hidl_cb) override;
::android::hardware::Return<Result> setProcessBuffers(const AudioBuffer& inBuffer,
const AudioBuffer& outBuffer) override;
::android::hardware::Return<void> command(uint32_t commandId,
const ::android::hardware::hidl_vec<uint8_t>& data,
uint32_t resultMaxSize, command_cb _hidl_cb) override;
::android::hardware::Return<Result> setParameter(
const ::android::hardware::hidl_vec<uint8_t>& parameter,
const ::android::hardware::hidl_vec<uint8_t>& value) override;
::android::hardware::Return<void> getParameter(
const ::android::hardware::hidl_vec<uint8_t>& parameter, uint32_t valueMaxSize,
getParameter_cb _hidl_cb) override;
::android::hardware::Return<void> getSupportedConfigsForFeature(
uint32_t featureId, uint32_t maxConfigs, uint32_t configSize,
getSupportedConfigsForFeature_cb _hidl_cb) override;
::android::hardware::Return<void> getCurrentConfigForFeature(
uint32_t featureId, uint32_t configSize,
getCurrentConfigForFeature_cb _hidl_cb) override;
::android::hardware::Return<Result> setCurrentConfigForFeature(
uint32_t featureId, const ::android::hardware::hidl_vec<uint8_t>& configData) override;
::android::hardware::Return<Result> close() override;
private:
const EffectDescriptor mDescriptor;
bool mEnabled = false;
};
} // namespace android::hardware::audio::effect::V7_0::implementation

View file

@ -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 <log/log.h>
#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<void> EffectsFactory::getAllDescriptors(getAllDescriptors_cb _hidl_cb) {
hidl_vec<EffectDescriptor> descriptors;
descriptors.resize(2);
descriptors[0] = EqualizerEffect::getDescriptor();
descriptors[1] = LoudnessEnhancerEffect::getDescriptor();
_hidl_cb(Result::OK, descriptors);
return Void();
}
Return<void> 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<void> 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<void> EffectsFactory::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) {
(void)fd;
(void)options;
return Void();
}
} // namespace android::hardware::audio::effect::V7_0::implementation

View file

@ -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 <android/hardware/audio/effect/7.0/IEffectsFactory.h>
namespace android::hardware::audio::effect::V7_0::implementation {
class EffectsFactory : public IEffectsFactory {
public:
EffectsFactory() = default;
::android::hardware::Return<void> getAllDescriptors(getAllDescriptors_cb _hidl_cb) override;
::android::hardware::Return<void> getDescriptor(
const ::android::hardware::audio::common::V7_0::Uuid& uuid,
getDescriptor_cb _hidl_cb) override;
::android::hardware::Return<void> 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<void>
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

View file

@ -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 <limits>
#define LOG_TAG "EffectsFactory7.0"
#include <log/log.h>
#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<uint8_t, 6>{{0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}},
.uuid = {0, 0, 0, 1, std::array<uint8_t, 6>{{0, 0, 0, 0, 0, 0}}}};
return descriptor;
}
EqualizerEffect::EqualizerEffect() : mEffect(new Effect(getDescriptor())) {
mProperties.bandLevels.resize(kNumBands);
}
Return<void> EqualizerEffect::getNumBands(getNumBands_cb _hidl_cb) {
_hidl_cb(Result::OK, kNumBands);
return Void();
}
Return<void> EqualizerEffect::getLevelRange(getLevelRange_cb _hidl_cb) {
_hidl_cb(Result::OK, std::numeric_limits<int16_t>::min(), std::numeric_limits<int16_t>::max());
return Void();
}
Return<Result> EqualizerEffect::setBandLevel(uint16_t band, int16_t level) {
if (band < kNumBands) {
mProperties.bandLevels[band] = level;
return Result::OK;
} else {
return Result::INVALID_ARGUMENTS;
}
}
Return<void> 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<void> EqualizerEffect::getBandCenterFrequency(uint16_t band,
getBandCenterFrequency_cb _hidl_cb) {
(void)band;
_hidl_cb(Result::OK, 0);
return Void();
}
Return<void> EqualizerEffect::getBandFrequencyRange(uint16_t band,
getBandFrequencyRange_cb _hidl_cb) {
(void)band;
_hidl_cb(Result::OK, 0, 1);
return Void();
}
Return<void> EqualizerEffect::getBandForFrequency(uint32_t freq, getBandForFrequency_cb _hidl_cb) {
(void)freq;
_hidl_cb(Result::OK, 0);
return Void();
}
Return<void> EqualizerEffect::getPresetNames(getPresetNames_cb _hidl_cb) {
hidl_vec<hidl_string> presetNames;
presetNames.resize(kNumPresets);
presetNames[0] = "default";
_hidl_cb(Result::OK, presetNames);
return Void();
}
Return<Result> EqualizerEffect::setCurrentPreset(uint16_t preset) {
if (preset < kNumPresets) {
mProperties.curPreset = preset;
return Result::OK;
} else {
return Result::INVALID_ARGUMENTS;
}
}
Return<void> EqualizerEffect::getCurrentPreset(getCurrentPreset_cb _hidl_cb) {
_hidl_cb(Result::OK, mProperties.curPreset);
return Void();
}
Return<Result> EqualizerEffect::setAllProperties(
const IEqualizerEffect::AllProperties& properties) {
mProperties = properties;
return Result::OK;
}
Return<void> EqualizerEffect::getAllProperties(getAllProperties_cb _hidl_cb) {
_hidl_cb(Result::OK, mProperties);
return Void();
}
} // namespace android::hardware::audio::effect::V7_0::implementation

View file

@ -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 <android/hardware/audio/effect/7.0/IEqualizerEffect.h>
#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<Result> init() override { return mEffect->init(); }
::android::hardware::Return<Result> setConfig(
const EffectConfig& config,
const ::android::sp<IEffectBufferProviderCallback>& inputBufferProvider,
const ::android::sp<IEffectBufferProviderCallback>& outputBufferProvider) override {
return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
}
::android::hardware::Return<Result> reset() override { return mEffect->reset(); }
::android::hardware::Return<Result> enable() override { return mEffect->enable(); }
::android::hardware::Return<Result> disable() override { return mEffect->disable(); }
::android::hardware::Return<Result> setDevice(
const ::android::hardware::audio::common::V7_0::DeviceAddress& device) override {
return mEffect->setDevice(device);
}
::android::hardware::Return<void> setAndGetVolume(
const ::android::hardware::hidl_vec<uint32_t>& volumes,
setAndGetVolume_cb _hidl_cb) override {
return mEffect->setAndGetVolume(volumes, _hidl_cb);
}
::android::hardware::Return<Result> volumeChangeNotification(
const ::android::hardware::hidl_vec<uint32_t>& volumes) override {
return mEffect->volumeChangeNotification(volumes);
}
::android::hardware::Return<Result> setAudioMode(
::android::hardware::audio::common::V7_0::AudioMode mode) override {
return mEffect->setAudioMode(mode);
}
::android::hardware::Return<Result> setConfigReverse(
const EffectConfig& config,
const ::android::sp<IEffectBufferProviderCallback>& inputBufferProvider,
const ::android::sp<IEffectBufferProviderCallback>& outputBufferProvider) override {
return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
}
::android::hardware::Return<Result> setInputDevice(
const ::android::hardware::audio::common::V7_0::DeviceAddress& device) override {
return mEffect->setInputDevice(device);
}
::android::hardware::Return<void> getConfig(getConfig_cb _hidl_cb) override {
return mEffect->getConfig(_hidl_cb);
}
::android::hardware::Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb) override {
return mEffect->getConfigReverse(_hidl_cb);
}
::android::hardware::Return<void> getSupportedAuxChannelsConfigs(
uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) override {
return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
}
::android::hardware::Return<void> getAuxChannelsConfig(
getAuxChannelsConfig_cb _hidl_cb) override {
return mEffect->getAuxChannelsConfig(_hidl_cb);
}
::android::hardware::Return<Result> setAuxChannelsConfig(
const EffectAuxChannelsConfig& config) override {
return mEffect->setAuxChannelsConfig(config);
}
::android::hardware::Return<Result> setAudioSource(
const ::android::hardware::hidl_string& source) override {
return mEffect->setAudioSource(source);
}
::android::hardware::Return<Result> offload(const EffectOffloadParameter& param) override {
return mEffect->offload(param);
}
::android::hardware::Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override {
return mEffect->getDescriptor(_hidl_cb);
}
::android::hardware::Return<void> prepareForProcessing(
prepareForProcessing_cb _hidl_cb) override {
return mEffect->prepareForProcessing(_hidl_cb);
}
::android::hardware::Return<Result> setProcessBuffers(const AudioBuffer& inBuffer,
const AudioBuffer& outBuffer) override {
return mEffect->setProcessBuffers(inBuffer, outBuffer);
}
::android::hardware::Return<void> command(uint32_t commandId,
const ::android::hardware::hidl_vec<uint8_t>& data,
uint32_t resultMaxSize,
command_cb _hidl_cb) override {
return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
}
::android::hardware::Return<Result> setParameter(
const ::android::hardware::hidl_vec<uint8_t>& parameter,
const ::android::hardware::hidl_vec<uint8_t>& value) override {
return mEffect->setParameter(parameter, value);
}
::android::hardware::Return<void> getParameter(
const ::android::hardware::hidl_vec<uint8_t>& parameter, uint32_t valueMaxSize,
getParameter_cb _hidl_cb) override {
return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
}
::android::hardware::Return<void> 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<void> getCurrentConfigForFeature(
uint32_t featureId, uint32_t configSize,
getCurrentConfigForFeature_cb _hidl_cb) override {
return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
}
::android::hardware::Return<Result> setCurrentConfigForFeature(
uint32_t featureId, const ::android::hardware::hidl_vec<uint8_t>& configData) override {
return mEffect->setCurrentConfigForFeature(featureId, configData);
}
::android::hardware::Return<Result> close() override { return mEffect->close(); }
// Methods from IEqualizerEffect interface.
::android::hardware::Return<void> getNumBands(getNumBands_cb _hidl_cb) override;
::android::hardware::Return<void> getLevelRange(getLevelRange_cb _hidl_cb) override;
::android::hardware::Return<Result> setBandLevel(uint16_t band, int16_t level) override;
::android::hardware::Return<void> getBandLevel(uint16_t band,
getBandLevel_cb _hidl_cb) override;
::android::hardware::Return<void> getBandCenterFrequency(
uint16_t band, getBandCenterFrequency_cb _hidl_cb) override;
::android::hardware::Return<void> getBandFrequencyRange(
uint16_t band, getBandFrequencyRange_cb _hidl_cb) override;
::android::hardware::Return<void> getBandForFrequency(uint32_t freq,
getBandForFrequency_cb _hidl_cb) override;
::android::hardware::Return<void> getPresetNames(getPresetNames_cb _hidl_cb) override;
::android::hardware::Return<Result> setCurrentPreset(uint16_t preset) override;
::android::hardware::Return<void> getCurrentPreset(getCurrentPreset_cb _hidl_cb) override;
::android::hardware::Return<Result> setAllProperties(
const IEqualizerEffect::AllProperties& properties) override;
::android::hardware::Return<void> getAllProperties(getAllProperties_cb _hidl_cb) override;
private:
static constexpr size_t kNumBands = 1;
static constexpr size_t kNumPresets = 1;
sp<Effect> mEffect;
IEqualizerEffect::AllProperties mProperties{};
};
} // namespace android::hardware::audio::effect::V7_0::implementation

View file

@ -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 <log/log.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 {
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<uint8_t, 6>{{0x11, 0x26, 0x0e, 0xb6, 0x3c, 0xf1}}},
.uuid = {0, 0, 0, 2, std::array<uint8_t, 6>{{0, 0, 0, 0, 0, 0}}}};
return descriptor;
} // namespace android::hardware::audio::effect::V7_0::implementation
LoudnessEnhancerEffect::LoudnessEnhancerEffect() : mEffect(new Effect(getDescriptor())) {}
Return<Result> LoudnessEnhancerEffect::setTargetGain(int32_t targetGainMb) {
mTargetGainMb = targetGainMb;
return Result::OK;
}
Return<void> LoudnessEnhancerEffect::getTargetGain(getTargetGain_cb _hidl_cb) {
_hidl_cb(Result::OK, mTargetGainMb);
return Void();
}
} // namespace android::hardware::audio::effect::V7_0::implementation

View file

@ -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 <android/hardware/audio/effect/7.0/ILoudnessEnhancerEffect.h>
#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<Result> init() override { return mEffect->init(); }
::android::hardware::Return<Result> setConfig(
const EffectConfig& config,
const ::android::sp<IEffectBufferProviderCallback>& inputBufferProvider,
const ::android::sp<IEffectBufferProviderCallback>& outputBufferProvider) override {
return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
}
::android::hardware::Return<Result> reset() override { return mEffect->reset(); }
::android::hardware::Return<Result> enable() override { return mEffect->enable(); }
::android::hardware::Return<Result> disable() override { return mEffect->disable(); }
::android::hardware::Return<Result> setDevice(
const ::android::hardware::audio::common::V7_0::DeviceAddress& device) override {
return mEffect->setDevice(device);
}
::android::hardware::Return<void> setAndGetVolume(
const ::android::hardware::hidl_vec<uint32_t>& volumes,
setAndGetVolume_cb _hidl_cb) override {
return mEffect->setAndGetVolume(volumes, _hidl_cb);
}
::android::hardware::Return<Result> volumeChangeNotification(
const ::android::hardware::hidl_vec<uint32_t>& volumes) override {
return mEffect->volumeChangeNotification(volumes);
}
::android::hardware::Return<Result> setAudioMode(
::android::hardware::audio::common::V7_0::AudioMode mode) override {
return mEffect->setAudioMode(mode);
}
::android::hardware::Return<Result> setConfigReverse(
const EffectConfig& config,
const ::android::sp<IEffectBufferProviderCallback>& inputBufferProvider,
const ::android::sp<IEffectBufferProviderCallback>& outputBufferProvider) override {
return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
}
::android::hardware::Return<Result> setInputDevice(
const ::android::hardware::audio::common::V7_0::DeviceAddress& device) override {
return mEffect->setInputDevice(device);
}
::android::hardware::Return<void> getConfig(getConfig_cb _hidl_cb) override {
return mEffect->getConfig(_hidl_cb);
}
::android::hardware::Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb) override {
return mEffect->getConfigReverse(_hidl_cb);
}
::android::hardware::Return<void> getSupportedAuxChannelsConfigs(
uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) override {
return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
}
::android::hardware::Return<void> getAuxChannelsConfig(
getAuxChannelsConfig_cb _hidl_cb) override {
return mEffect->getAuxChannelsConfig(_hidl_cb);
}
::android::hardware::Return<Result> setAuxChannelsConfig(
const EffectAuxChannelsConfig& config) override {
return mEffect->setAuxChannelsConfig(config);
}
::android::hardware::Return<Result> setAudioSource(
const ::android::hardware::hidl_string& source) override {
return mEffect->setAudioSource(source);
}
::android::hardware::Return<Result> offload(const EffectOffloadParameter& param) override {
return mEffect->offload(param);
}
::android::hardware::Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override {
return mEffect->getDescriptor(_hidl_cb);
}
::android::hardware::Return<void> prepareForProcessing(
prepareForProcessing_cb _hidl_cb) override {
return mEffect->prepareForProcessing(_hidl_cb);
}
::android::hardware::Return<Result> setProcessBuffers(const AudioBuffer& inBuffer,
const AudioBuffer& outBuffer) override {
return mEffect->setProcessBuffers(inBuffer, outBuffer);
}
::android::hardware::Return<void> command(uint32_t commandId,
const ::android::hardware::hidl_vec<uint8_t>& data,
uint32_t resultMaxSize,
command_cb _hidl_cb) override {
return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
}
::android::hardware::Return<Result> setParameter(
const ::android::hardware::hidl_vec<uint8_t>& parameter,
const ::android::hardware::hidl_vec<uint8_t>& value) override {
return mEffect->setParameter(parameter, value);
}
::android::hardware::Return<void> getParameter(
const ::android::hardware::hidl_vec<uint8_t>& parameter, uint32_t valueMaxSize,
getParameter_cb _hidl_cb) override {
return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
}
::android::hardware::Return<void> 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<void> getCurrentConfigForFeature(
uint32_t featureId, uint32_t configSize,
getCurrentConfigForFeature_cb _hidl_cb) override {
return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
}
::android::hardware::Return<Result> setCurrentConfigForFeature(
uint32_t featureId, const ::android::hardware::hidl_vec<uint8_t>& configData) override {
return mEffect->setCurrentConfigForFeature(featureId, configData);
}
::android::hardware::Return<Result> close() override { return mEffect->close(); }
// Methods from ILoudnessEnhancerEffect interface.
::android::hardware::Return<Result> setTargetGain(int32_t targetGainMb) override;
::android::hardware::Return<void> getTargetGain(getTargetGain_cb _hidl_cb) override;
private:
sp<Effect> mEffect;
int32_t mTargetGainMb = 0;
};
} // namespace android::hardware::audio::effect::V7_0::implementation

View file

@ -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

View file

@ -0,0 +1,20 @@
<manifest version="1.0" type="device">
<hal format="hidl">
<name>android.hardware.audio</name>
<transport>hwbinder</transport>
<version>7.0</version>
<interface>
<name>IDevicesFactory</name>
<instance>example</instance>
</interface>
</hal>
<hal format="hidl">
<name>android.hardware.audio.effect</name>
<transport>hwbinder</transport>
<version>7.0</version>
<interface>
<name>IEffectsFactory</name>
<instance>example</instance>
</interface>
</hal>
</manifest>

View file

@ -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 <hidl/HidlTransportSupport.h>
#include <log/log.h>
#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;
}

View file

@ -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<AudioChannelMask> 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<uint32_t> 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<vec<AudioChannelMask>> 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<uint32_t> sampleRates;
/** List of channel masks supported by the profile. */
vec<AudioChannelMask> channelMasks;
};
vec<AudioProfile> profiles;
/** List of gain controls attached to the port. */
vec<AudioGain> gains;

View file

@ -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<common::CPP_VERSION::AudioDevice> AudioDeviceBitfield;
typedef hidl_bitfield<common::CPP_VERSION::AudioChannelMask> AudioChannelBitfield;
typedef hidl_bitfield<common::CPP_VERSION::AudioOutputFlag> AudioOutputFlagBitfield;

View file

@ -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;

View file

@ -16,6 +16,13 @@
#include "AudioPrimaryHidlHalTest.h"
#if MAJOR_VERSION >= 7
#include <audio_policy_configuration_V7_0.h>
#include <xsdc/XsdcSupport.h>
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>(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<hidl_string> 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<IStreamIn> 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<AudioSource> range;
#elif MAJOR_VERSION >= 7
xsdc_enum_range<audio::policy::configuration::V7_0::AudioSource> 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<AudioUsage> usageRange;
hidl_enum_range<AudioContentType> contentRange;
#elif MAJOR_VERSION >= 7
xsdc_enum_range<audio::policy::configuration::V7_0::AudioUsage> usageRange;
xsdc_enum_range<audio::policy::configuration::V7_0::AudioContentType> 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({}));

View file

@ -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<AudioFormat>& capabilities) {
Result res;
EXPECT_OK(stream->getSupportedFormats(returnIn(res, capabilities)));
@ -88,6 +89,7 @@ struct GetSupported {
}
#endif
};
#endif // MAJOR_VERSION <= 6
template <class T>
auto dump(T t, hidl_handle handle) {

View file

@ -17,6 +17,7 @@
// pull in all the <= 5.0 tests
#include "5.0/AudioPrimaryHidlHalTest.cpp"
#if MAJOR_VERSION <= 6
const std::vector<DeviceConfigParameter>& getOutputDeviceConfigParameters() {
static std::vector<DeviceConfigParameter> parameters = [] {
std::vector<DeviceConfigParameter> result;
@ -28,8 +29,8 @@ const std::vector<DeviceConfigParameter>& getOutputDeviceConfigParameters() {
const auto& channels = profile->getChannels();
const auto& sampleRates = profile->getSampleRates();
auto configs = ConfigHelper::combineAudioConfig(
vector<audio_channel_mask_t>(channels.begin(), channels.end()),
vector<uint32_t>(sampleRates.begin(), sampleRates.end()),
std::vector<audio_channel_mask_t>(channels.begin(), channels.end()),
std::vector<uint32_t>(sampleRates.begin(), sampleRates.end()),
profile->getFormat());
auto flags = ioProfile->getFlags();
for (auto& config : configs) {
@ -46,8 +47,8 @@ const std::vector<DeviceConfigParameter>& 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<DeviceConfigParameter>& getInputDeviceConfigParameters() {
const auto& channels = profile->getChannels();
const auto& sampleRates = profile->getSampleRates();
auto configs = ConfigHelper::combineAudioConfig(
vector<audio_channel_mask_t>(channels.begin(), channels.end()),
vector<uint32_t>(sampleRates.begin(), sampleRates.end()),
std::vector<audio_channel_mask_t>(channels.begin(), channels.end()),
std::vector<uint32_t>(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<DeviceConfigParameter>& 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>(AudioOutputFlag::NONE);
SourceMetadata initMetadata = {{{AudioUsage::MEDIA, AudioContentType::MUSIC, 1 /* gain */}}};
auto flags = hidl_bitfield<AudioOutputFlag>(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<AudioInOutFlag> flags;
#endif
AudioConfig config{};
sp<IStreamOut> stream;
StreamHelper<IStreamOut> 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>(AudioInputFlag::NONE);
SinkMetadata initMetadata = {{{.source = AudioSource::MIC, .gain = 1}}};
auto flags = hidl_bitfield<AudioInputFlag>(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<AudioInOutFlag> flags;
#endif
AudioConfig config{};
sp<IStreamIn> stream;
StreamHelper<IStreamIn> 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<int32_t>(AudioHandleConsts::AUDIO_PATCH_HANDLE_NONE),
hidl_vec<AudioPortConfig>(), hidl_vec<AudioPortConfig>(), returnIn(res, ignored)));
ASSERT_OK(getDevice()->updateAudioPatch(AudioPatchHandle{}, hidl_vec<AudioPortConfig>(),
hidl_vec<AudioPortConfig>(), returnIn(res, ignored)));
ASSERT_RESULT(Result::INVALID_ARGUMENTS, res);
}

View file

@ -16,3 +16,101 @@
// pull in all the <= 6.0 tests
#include "6.0/AudioPrimaryHidlHalTest.cpp"
static std::vector<AudioConfig> combineAudioConfig(std::vector<xsd::AudioChannelMask> channelMasks,
std::vector<int64_t> sampleRates,
const std::string& format) {
std::vector<AudioConfig> 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<DeviceConfigParameter>& getOutputDeviceConfigParameters() {
static std::vector<DeviceConfigParameter> parameters = [] {
std::vector<DeviceConfigParameter> result;
const std::vector<AudioInOutFlag> 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<PARAM_DEVICE_NAME>(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<AudioInOutFlag> 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<DeviceConfigParameter>& getInputDeviceConfigParameters() {
static std::vector<DeviceConfigParameter> parameters = [] {
std::vector<DeviceConfigParameter> result;
for (const auto& device : getDeviceParameters()) {
auto module =
getCachedPolicyConfig().getModuleFromName(std::get<PARAM_DEVICE_NAME>(device));
for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
if (mixPort.getRole() != xsd::Role::sink) continue; // not an input profile
std::vector<AudioInOutFlag> 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;
}

View file

@ -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<std::string>& 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<xsd::AudioPolicyConfiguration> mConfig;
status_t mStatus = NO_INIT;
const xsd::Module* mPrimaryModule;
std::set<std::string> mModulesWithDevicesNames;
};

View file

@ -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",

View file

@ -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 <audio_policy_configuration_V7_0-enums.h>
#include <audio_policy_configuration_V7_0.h>
#endif
#include <Serializer.h>
#include <fmq/EventFlag.h>
#include <fmq/MessageQueue.h>
#include <hidl/GtestPrinter.h>
@ -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<android::DeviceDescriptor> 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<const HwModule> getModuleFromName(const std::string& name) const {
return getHwModules().getModuleFromName(name.c_str());
}
sp<const HwModule> getPrimaryModule() const { return mPrimaryModule; }
const std::set<std::string>& getModulesWithDevicesNames() const {
return mModulesWithDevicesNames;
}
private:
status_t mStatus = NO_INIT;
std::string mFilePath;
sp<HwModule> mPrimaryModule = nullptr;
std::set<std::string> 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> policyConfig = [] {
auto config = std::make_unique<PolicyConfig>();
auto config = std::make_unique<PolicyConfig>(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 <Optionality optionality = REQUIRED, class IUTGetter, class Getter, class Setter>
void testAccessors(IUTGetter iutGetter, const string& propertyName,
const Initial expectedInitial, list<Property> valuesToTest, Setter setter,
Getter getter, const vector<Property>& invalidValues = {}) {
void testAccessors(IUTGetter iutGetter, const std::string& propertyName,
const Initial expectedInitial, std::list<Property> valuesToTest,
Setter setter, Getter getter,
const std::vector<Property>& 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 <Optionality optionality = REQUIRED, class Getter, class Setter>
void testAccessors(const string& propertyName, const Initial expectedInitial,
list<Property> valuesToTest, Setter setter, Getter getter,
const vector<Property>& invalidValues = {}) {
void testAccessors(const std::string& propertyName, const Initial expectedInitial,
std::list<Property> valuesToTest, Setter setter, Getter getter,
const std::vector<Property>& invalidValues = {}) {
testAccessors<optionality>(&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<DeviceParameter, AudioConfig, std::variant<AudioInputFlag, AudioOutputFlag>>;
#elif MAJOR_VERSION >= 7
using DeviceConfigParameter = std::tuple<DeviceParameter, AudioConfig, std::vector<AudioInOutFlag>>;
#endif
#if MAJOR_VERSION >= 6
const std::vector<DeviceConfigParameter>& getInputDeviceConfigParameters();
@ -583,8 +526,8 @@ const std::vector<DeviceConfigParameter>& 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<DeviceConfigParameter>& info) {
const AudioConfig& config = std::get<PARAM_CONFIG>(info.param);
const auto deviceName = DeviceParameterToString(::testing::TestParamInfo<DeviceParameter>{
std::get<PARAM_DEVICE>(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<PARAM_FLAGS>(info.param));
#elif MAJOR_VERSION >= 4
SanitizeStringForGTestName(std::visit(
[](auto&& arg) -> std::string {
using T = std::decay_t<decltype(arg)>;
// Need to use FQN of toString to avoid confusing the compiler
return ::android::hardware::audio::common::CPP_VERSION::toString<T>(
hidl_bitfield<T>(arg));
},
std::get<PARAM_FLAGS>(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<PARAM_FLAGS>(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<decltype(arg)>;
// Need to use FQN of toString to avoid confusing the compiler
return ::android::hardware::audio::common::CPP_VERSION::toString<T>(
hidl_bitfield<T>(arg));
},
std::get<PARAM_FLAGS>(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<PARAM_FLAGS>(info.param)));
#endif
return devicePart + "__" + configPart;
}
class AudioHidlTestWithDeviceConfigParameter
@ -660,7 +617,7 @@ class AudioHidlTestWithDeviceConfigParameter
AudioOutputFlag getOutputFlags() const {
return std::get<INDEX_OUTPUT>(std::get<PARAM_FLAGS>(GetParam()));
}
#elif MAJOR_VERSION >= 4
#elif MAJOR_VERSION >= 4 && MAJOR_VERSION <= 6
hidl_bitfield<AudioInputFlag> getInputFlags() const {
return hidl_bitfield<AudioInputFlag>(
std::get<INDEX_INPUT>(std::get<PARAM_FLAGS>(GetParam())));
@ -669,10 +626,17 @@ class AudioHidlTestWithDeviceConfigParameter
return hidl_bitfield<AudioOutputFlag>(
std::get<INDEX_OUTPUT>(std::get<PARAM_FLAGS>(GetParam())));
}
#elif MAJOR_VERSION >= 7
hidl_vec<AudioInOutFlag> getInputFlags() const { return std::get<PARAM_FLAGS>(GetParam()); }
hidl_vec<AudioInOutFlag> getOutputFlags() const { return std::get<PARAM_FLAGS>(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<IStreamOut> {
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<IStreamOut> {
},
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<IStreamIn> {
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<IStreamIn> {
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 <class Property, class CapabilityGetter>
static void testCapabilityGetter(const string& name, IStream* stream,
static void testCapabilityGetter(const std::string& name, IStream* stream,
CapabilityGetter capabilityGetter,
Return<Property> (IStream::*getter)(),
Return<Result> (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<AudioProfile> 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<AudioProfile> 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<AudioChannelMask>({});
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<hidl_string> keys,
initializer_list<Result> expectedResults) {
std::initializer_list<Result> expectedResults) {
hidl_vec<ParameterValue> 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<Return<Result>(float)> setGain) {
@ -1286,7 +1326,7 @@ static void testUnitaryGain(std::function<Return<Result>(float)> setGain) {
}
static void testOptionalUnitaryGain(std::function<Return<Result>(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);
}

View file

@ -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<AudioConfig> getRequiredSupportPlaybackAudioConfig() {
static const std::vector<AudioConfig> getRequiredSupportPlaybackAudioConfig() {
return combineAudioConfig({AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO},
{8000, 11025, 16000, 22050, 32000, 44100},
{AudioFormat::PCM_16_BIT});
}
static const vector<AudioConfig> getRecommendedSupportPlaybackAudioConfig() {
static const std::vector<AudioConfig> getRecommendedSupportPlaybackAudioConfig() {
return combineAudioConfig({AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO},
{24000, 48000}, {AudioFormat::PCM_16_BIT});
}
static const vector<AudioConfig> getRequiredSupportCaptureAudioConfig() {
static const std::vector<AudioConfig> getRequiredSupportCaptureAudioConfig() {
if (!primaryHasMic()) return {};
return combineAudioConfig({AudioChannelMask::IN_MONO}, {8000, 11025, 16000, 44100},
{AudioFormat::PCM_16_BIT});
}
static const vector<AudioConfig> getRecommendedSupportCaptureAudioConfig() {
static const std::vector<AudioConfig> getRecommendedSupportCaptureAudioConfig() {
if (!primaryHasMic()) return {};
return combineAudioConfig({AudioChannelMask::IN_STEREO}, {22050, 48000},
{AudioFormat::PCM_16_BIT});
}
static vector<AudioConfig> combineAudioConfig(vector<audio_channel_mask_t> channelMasks,
vector<uint32_t> sampleRates,
audio_format_t format) {
vector<AudioConfig> configs;
static std::vector<AudioConfig> combineAudioConfig(
std::vector<audio_channel_mask_t> channelMasks, std::vector<uint32_t> sampleRates,
audio_format_t format) {
std::vector<AudioConfig> 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<AudioConfig> combineAudioConfig(vector<AudioChannelMask> channelMasks,
vector<uint32_t> sampleRates,
vector<AudioFormat> formats) {
vector<AudioConfig> configs;
static std::vector<AudioConfig> combineAudioConfig(std::vector<AudioChannelMask> channelMasks,
std::vector<uint32_t> sampleRates,
std::vector<AudioFormat> formats) {
std::vector<AudioConfig> configs;
configs.reserve(channelMasks.size() * sampleRates.size() * formats.size());
for (auto channelMask : channelMasks) {
for (auto sampleRate : sampleRates) {

View file

@ -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 Derived, class Key, class Interface>
class InterfaceManager {

View file

@ -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 <Serializer.h>
struct PolicyConfigData {
android::HwModuleCollection hwModules;
android::DeviceVector availableOutputDevices;
android::DeviceVector availableInputDevices;
sp<android::DeviceDescriptor> 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<const android::HwModule> getModuleFromName(const std::string& name) const {
return getHwModules().getModuleFromName(name.c_str());
}
sp<const android::HwModule> getPrimaryModule() const { return mPrimaryModule; }
const std::set<std::string>& 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<const android::HwModule> mPrimaryModule = nullptr;
std::set<std::string> mModulesWithDevicesNames;
};

View file

@ -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: [

View file

@ -16,7 +16,9 @@
#define LOG_TAG "AudioEffectHidlHalTest"
#include <android-base/logging.h>
#if MAJOR_VERSION <= 6
#include <system/audio.h>
#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 <android/hidl/allocator/1.0/IAllocator.h>
#include <android/hidl/memory/1.0/IMemory.h>
#if MAJOR_VERSION >= 7
#include <audio_policy_configuration_V7_0-enums.h>
#include <audio_policy_configuration_V7_0.h>
#endif
#include <common/all-versions/VersionUtils.h>
@ -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<EffectParameter> {
effectsFactory = IEffectsFactory::getService(std::get<PARAM_FACTORY_NAME>(GetParam()));
ASSERT_NE(nullptr, effectsFactory.get());
findAndCreateEffect(getEffectType());
ASSERT_NO_FATAL_FAILURE(findAndCreateEffect(getEffectType()));
ASSERT_NE(nullptr, effect.get());
Return<Result> ret = effect->init();
@ -201,7 +213,7 @@ class AudioEffectHidlTest : public ::testing::TestWithParam<EffectParameter> {
void AudioEffectHidlTest::findAndCreateEffect(const Uuid& type) {
Uuid effectUuid;
findEffectInstance(type, &effectUuid);
ASSERT_NO_FATAL_FAILURE(findEffectInstance(type, &effectUuid));
Return<void> 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<audio_channel_mask_t>(currentConfig.outputCfg.channels)));
*channelCount = audio_channel_count_from_out_mask(
static_cast<audio_channel_mask_t>(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<Result> ret = effect->setDevice(mkEnumBitfield(AudioDevice::OUT_SPEAKER));
#else
DeviceAddress device{.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_SPEAKER)};
Return<Result> 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<Result> ret = effect->setInputDevice(mkEnumBitfield(AudioDevice::IN_BUILTIN_MIC));
#else
DeviceAddress device{.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_IN_BUILTIN_MIC)};
Return<Result> 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<Result> ret = effect->setAudioSource(AudioSource::MIC);
#else
Return<Result> 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<int>(AudioHandleConsts::AUDIO_IO_HANDLE_NONE);
Return<Result> ret = effect->offload(offloadParam);
Return<Result> ret = effect->offload(EffectOffloadParameter{});
EXPECT_TRUE(ret.isOk());
}