diff options
Diffstat (limited to 'emulator/audio')
-rw-r--r-- | emulator/audio/audio_policy_configuration.xml | 61 | ||||
-rw-r--r-- | emulator/audio/car_audio_configuration.xml | 52 | ||||
-rw-r--r-- | emulator/audio/car_emulator_audio.mk | 5 | ||||
-rw-r--r-- | emulator/audio/driver/Android.bp | 1 | ||||
-rw-r--r-- | emulator/audio/driver/android.hardware.audio@6.0-impl.xml | 25 | ||||
-rw-r--r-- | emulator/audio/driver/audio_hw.c | 233 | ||||
-rw-r--r-- | emulator/audio/driver/audio_hw.h | 12 |
7 files changed, 309 insertions, 80 deletions
diff --git a/emulator/audio/audio_policy_configuration.xml b/emulator/audio/audio_policy_configuration.xml index 9b81599..ed0f4a6 100644 --- a/emulator/audio/audio_policy_configuration.xml +++ b/emulator/audio/audio_policy_configuration.xml @@ -59,11 +59,16 @@ <item>bus5_alarm_out</item> <item>bus6_notification_out</item> <item>bus7_system_sound_out</item> - <item>bus100_rear_seat</item> + <!-- names with _audio_zone_# are used for defined an emulator rear seat audio zone + where each number # is the zone id number --> + <item>bus100_audio_zone_1</item> + <item>bus200_audio_zone_2</item> <item>Built-In Mic</item> <item>Built-In Back Mic</item> <item>Echo-Reference Mic</item> <item>FM Tuner</item> + <item>Tone Generator 0</item> + <item>Tone Generator 1</item> </attachedDevices> <defaultOutputDevice>bus0_media_out</defaultOutputDevice> <mixPorts> @@ -115,12 +120,18 @@ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> </mixPort> - <mixPort name="mixport_bus100_rear_seat" role="source" + <mixPort name="mixport_bus100_audio_zone_1" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> </mixPort> + <mixPort name="mixport_bus200_audio_zone_2" role="source" + flags="AUDIO_OUTPUT_FLAG_PRIMARY"> + <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" + samplingRates="48000" + channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> + </mixPort> <mixPort name="primary input" role="sink"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000" @@ -131,6 +142,16 @@ samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_STEREO"/> </mixPort> + <mixPort name="mixport_input_bus_tone_zone_0" role="sink"> + <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" + samplingRates="48000" + channelMasks="AUDIO_CHANNEL_IN_STEREO"/> + </mixPort> + <mixPort name="mixport_input_bus_tone_zone_1" role="sink"> + <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" + samplingRates="48000" + channelMasks="AUDIO_CHANNEL_IN_STEREO"/> + </mixPort> </mixPorts> <devicePorts> <devicePort tagName="bus0_media_out" role="sink" type="AUDIO_DEVICE_OUT_BUS" @@ -205,8 +226,8 @@ minValueMB="-3200" maxValueMB="600" defaultValueMB="0" stepValueMB="100"/> </gains> </devicePort> - <devicePort tagName="bus100_rear_seat" role="sink" type="AUDIO_DEVICE_OUT_BUS" - address="bus100_rear_seat"> + <devicePort tagName="bus100_audio_zone_1" role="sink" type="AUDIO_DEVICE_OUT_BUS" + address="bus100_audio_zone_1"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> <gains> @@ -214,6 +235,15 @@ minValueMB="-3200" maxValueMB="600" defaultValueMB="0" stepValueMB="100"/> </gains> </devicePort> + <devicePort tagName="bus200_audio_zone_2" role="sink" type="AUDIO_DEVICE_OUT_BUS" + address="bus200_audio_zone_2"> + <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" + samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> + <gains> + <gain name="" mode="AUDIO_GAIN_MODE_JOINT" + minValueMB="-3200" maxValueMB="600" defaultValueMB="0" stepValueMB="100"/> + </gains> + </devicePort> <devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000" @@ -238,6 +268,24 @@ minValueMB="-3200" maxValueMB="600" defaultValueMB="0" stepValueMB="100"/> </gains> </devicePort> + <devicePort tagName="Tone Generator 0" type="AUDIO_DEVICE_IN_BUS" role="source" + address="input_bus_tone_zone_0"> + <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" + samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_STEREO"/> + <gains> + <gain name="" mode="AUDIO_GAIN_MODE_JOINT" + minValueMB="-3200" maxValueMB="600" defaultValueMB="0" stepValueMB="100"/> + </gains> + </devicePort> + <devicePort tagName="Tone Generator 1" type="AUDIO_DEVICE_IN_BUS" role="source" + address="input_bus_tone_zone_1"> + <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" + samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_STEREO"/> + <gains> + <gain name="" mode="AUDIO_GAIN_MODE_JOINT" + minValueMB="-3200" maxValueMB="600" defaultValueMB="0" stepValueMB="100"/> + </gains> + </devicePort> </devicePorts> <!-- route declaration, i.e. list all available sources for a given sink --> <routes> @@ -249,9 +297,12 @@ <route type="mix" sink="bus5_alarm_out" sources="mixport_bus5_alarm_out"/> <route type="mix" sink="bus6_notification_out" sources="mixport_bus6_notification_out"/> <route type="mix" sink="bus7_system_sound_out" sources="mixport_bus7_system_sound_out"/> - <route type="mix" sink="bus100_rear_seat" sources="mixport_bus100_rear_seat"/> + <route type="mix" sink="bus100_audio_zone_1" sources="mixport_bus100_audio_zone_1"/> + <route type="mix" sink="bus200_audio_zone_2" sources="mixport_bus200_audio_zone_2"/> <route type="mix" sink="primary input" sources="Built-In Mic,Built-In Back Mic,Echo-Reference Mic"/> <route type="mix" sink="mixport_tuner0" sources="FM Tuner"/> + <route type="mix" sink="mixport_input_bus_tone_zone_0" sources="Tone Generator 0"/> + <route type="mix" sink="mixport_input_bus_tone_zone_1" sources="Tone Generator 1"/> </routes> </module> diff --git a/emulator/audio/car_audio_configuration.xml b/emulator/audio/car_audio_configuration.xml index 7d3cf01..d79ff33 100644 --- a/emulator/audio/car_audio_configuration.xml +++ b/emulator/audio/car_audio_configuration.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2018 The Android Open Source Project +<!-- 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. @@ -17,14 +17,13 @@ <!-- Defines the audio configuration in a car, including - Audio zones - - Display to audio zone mappings - Context to audio bus mappings - Volume groups in the car environment. --> -<carAudioConfiguration version="1"> +<carAudioConfiguration version="2"> <zones> - <zone name="primary zone" isPrimary="true"> + <zone name="primary zone" isPrimary="true" occupantZoneId="0"> <volumeGroups> <group> <device address="bus0_media_out"> @@ -38,6 +37,10 @@ </device> <device address="bus7_system_sound_out"> <context context="system_sound"/> + <context context="emergency"/> + <context context="safety"/> + <context context="vehicle_status"/> + <context context="announcement"/> </device> </group> <group> @@ -59,21 +62,11 @@ </device> </group> </volumeGroups> - <displays> - <display port="0"/> - </displays> - <!-- to specify displays associated with this audio zone, use the following tags - <displays> - <display port="1"/> - <display port="2"/> - </displays> - where port is the physical port of the display (See DisplayAddress.Phyisical) - --> </zone> - <zone name="rear seat zone"> + <zone name="rear seat zone 1" audioZoneId="1"> <volumeGroups> <group> - <device address="bus100_rear_seat"> + <device address="bus100_audio_zone_1"> <context context="music"/> <context context="navigation"/> <context context="voice_command"/> @@ -82,12 +75,33 @@ <context context="alarm"/> <context context="notification"/> <context context="system_sound"/> + <context context="emergency"/> + <context context="safety"/> + <context context="vehicle_status"/> + <context context="announcement"/> + </device> + </group> + </volumeGroups> + </zone> + <zone name="rear seat zone 2" audioZoneId="2"> + <volumeGroups> + <group> + <device address="bus200_audio_zone_2"> + <context context="music"/> + <context context="navigation"/> + <context context="voice_command"/> + <context context="call_ring"/> + <context context="call"/> + <context context="alarm"/> + <context context="notification"/> + <context context="system_sound"/> + <context context="emergency"/> + <context context="safety"/> + <context context="vehicle_status"/> + <context context="announcement"/> </device> </group> </volumeGroups> - <displays> - <display port="1"/> - </displays> </zone> </zones> </carAudioConfiguration> diff --git a/emulator/audio/car_emulator_audio.mk b/emulator/audio/car_emulator_audio.mk index bef5c2e..6e29916 100644 --- a/emulator/audio/car_emulator_audio.mk +++ b/emulator/audio/car_emulator_audio.mk @@ -13,9 +13,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -USE_XML_AUDIO_POLICY_CONF := 1 - PRODUCT_PACKAGES += audio.primary.caremu +PRODUCT_PACKAGES += \ + android.hardware.audio@6.0-impl:32 + PRODUCT_PROPERTY_OVERRIDES += ro.hardware.audio.primary=caremu PRODUCT_COPY_FILES += \ diff --git a/emulator/audio/driver/Android.bp b/emulator/audio/driver/Android.bp index b0c2c34..5cf177c 100644 --- a/emulator/audio/driver/Android.bp +++ b/emulator/audio/driver/Android.bp @@ -18,6 +18,7 @@ cc_library_shared { vendor: true, + vintf_fragments: ["android.hardware.audio@6.0-impl.xml"], name: "audio.primary.caremu", relative_install_path: "hw", diff --git a/emulator/audio/driver/android.hardware.audio@6.0-impl.xml b/emulator/audio/driver/android.hardware.audio@6.0-impl.xml new file mode 100644 index 0000000..2814739 --- /dev/null +++ b/emulator/audio/driver/android.hardware.audio@6.0-impl.xml @@ -0,0 +1,25 @@ +<!-- 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. +--> +<manifest version="1.0" type="device"> + <hal format="hidl"> + <name>android.hardware.audio</name> + <transport>hwbinder</transport> + <version>6.0</version> + <interface> + <name>IDevicesFactory</name> + <instance>default</instance> + </interface> + </hal> +</manifest>
\ No newline at end of file diff --git a/emulator/audio/driver/audio_hw.c b/emulator/audio/driver/audio_hw.c index 13cb72b..bc27e90 100644 --- a/emulator/audio/driver/audio_hw.c +++ b/emulator/audio/driver/audio_hw.c @@ -51,9 +51,29 @@ #define IN_PERIOD_MS 15 #define IN_PERIOD_COUNT 4 +#define PI 3.14159265 +#define TWO_PI (2*PI) + +// 150 Hz +#define DEFAULT_FREQUENCY 150 +// Increase in changes to tone frequency +#define TONE_FREQUENCY_INCREASE 20 +// Max tone frequency to auto assign, don't want to generate too high of a pitch +#define MAX_TONE_FREQUENCY 500 + #define _bool_str(x) ((x)?"true":"false") -#define PROP_KEY_SIMULATE_MULTI_ZONE_AUDIO "ro.aae.simulateMultiZoneAudio" +static const char * const PROP_KEY_SIMULATE_MULTI_ZONE_AUDIO = "ro.aae.simulateMultiZoneAudio"; +static const char * const AAE_PARAMETER_KEY_FOR_SELECTED_ZONE = "com.android.car.emulator.selected_zone"; +#define PRIMARY_ZONE_ID 0 +#define INVALID_ZONE_ID -1 +// Note the primary zone goes to left speaker so route other zone to right speaker +#define DEFAULT_ZONE_TO_LEFT_SPEAKER (PRIMARY_ZONE_ID + 1) + +static const char * const TONE_ADDRESS_KEYWORD = "_tone_"; +static const char * const AUDIO_ZONE_KEYWORD = "_audio_zone_"; + +#define SIZE_OF_PARSE_BUFFER 32 static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state); @@ -66,6 +86,22 @@ static struct pcm_config pcm_config_out = { .start_threshold = 0, }; +static int get_int_value(const struct str_parms *str_parms, const char *key, int *return_value) { + char value[SIZE_OF_PARSE_BUFFER]; + int results = str_parms_get_str(str_parms, key, value, SIZE_OF_PARSE_BUFFER); + if (results >= 0) { + char *end = NULL; + errno = 0; + long val = strtol(value, &end, 10); + if ((errno == 0) && (end != NULL) && (*end == '\0') && ((int) val == val)) { + *return_value = val; + } else { + results = -EINVAL; + } + } + return results; +} + static struct pcm_config pcm_config_in = { .channels = 2, .rate = 0, @@ -79,6 +115,18 @@ static struct pcm_config pcm_config_in = { static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER; static unsigned int audio_device_ref_count = 0; +static bool is_zone_selected_to_play(struct audio_hw_device *dev, int zone_id) { + // play if current zone is enable or zone equal to primary zone + bool is_selected_zone = true; + if (zone_id != PRIMARY_ZONE_ID) { + struct generic_audio_device *adev = (struct generic_audio_device *)dev; + pthread_mutex_lock(&adev->lock); + is_selected_zone = adev->last_zone_selected_to_play == zone_id; + pthread_mutex_unlock(&adev->lock); + } + return is_selected_zone; +} + static uint32_t out_get_sample_rate(const struct audio_stream *stream) { struct generic_stream_out *out = (struct generic_stream_out *)stream; return out->req_config.sample_rate; @@ -139,10 +187,7 @@ static int out_dump(const struct audio_stream *stream, int fd) { static int out_set_parameters(struct audio_stream *stream, const char *kvpairs) { struct generic_stream_out *out = (struct generic_stream_out *)stream; struct str_parms *parms; - char value[32]; - int ret; - long val; - char *end; + int ret = 0; pthread_mutex_lock(&out->lock); if (!out->standby) { @@ -150,17 +195,11 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs) ret = -ENOSYS; } else { parms = str_parms_create_str(kvpairs); - ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, - value, sizeof(value)); + int val = 0; + ret = get_int_value(parms, AUDIO_PARAMETER_STREAM_ROUTING, &val); if (ret >= 0) { - errno = 0; - val = strtol(value, &end, 10); - if (errno == 0 && (end != NULL) && (*end == '\0') && ((int)val == val)) { - out->device = (int)val; - ret = 0; - } else { - ret = -EINVAL; - } + out->device = (int)val; + ret = 0; } str_parms_destroy(parms); } @@ -201,6 +240,19 @@ static int out_set_volume(struct audio_stream_out *stream, return -ENOSYS; } +static int get_zone_id_from_address(const char *address) { + int zone_id = INVALID_ZONE_ID; + char *zone_start = strstr(address, AUDIO_ZONE_KEYWORD); + if (zone_start) { + char *end = NULL; + zone_id = strtol(zone_start + strlen(AUDIO_ZONE_KEYWORD), &end, 10); + if (end == NULL || zone_id < 0) { + return INVALID_ZONE_ID; + } + } + return zone_id; +} + static void *out_write_worker(void *args) { struct generic_stream_out *out = (struct generic_stream_out *)args; struct ext_pcm *ext_pcm = NULL; @@ -209,6 +261,18 @@ static void *out_write_worker(void *args) { int buffer_size; bool restart = false; bool shutdown = false; + int zone_id = PRIMARY_ZONE_ID; + // If it is a audio zone keyword bus address then get zone id + if (strstr(out->bus_address, AUDIO_ZONE_KEYWORD)) { + zone_id = get_zone_id_from_address(out->bus_address); + if (zone_id == INVALID_ZONE_ID) { + ALOGE("%s Found invalid zone id, defaulting device %s to zone %d", __func__, + out->bus_address, DEFAULT_ZONE_TO_LEFT_SPEAKER); + zone_id = DEFAULT_ZONE_TO_LEFT_SPEAKER; + } + } + ALOGD("Out worker:%s zone id %d", out->bus_address, zone_id); + while (true) { pthread_mutex_lock(&out->lock); while (out->worker_standby || restart) { @@ -265,13 +329,17 @@ static void *out_write_worker(void *args) { } int frames = audio_vbuffer_read(&out->buffer, buffer, buffer_frames); pthread_mutex_unlock(&out->lock); - int write_error = ext_pcm_write(ext_pcm, out->bus_address, + + if (is_zone_selected_to_play(out->dev, zone_id)) { + int write_error = ext_pcm_write(ext_pcm, out->bus_address, buffer, ext_pcm_frames_to_bytes(ext_pcm, frames)); - if (write_error) { - ALOGE("pcm_write failed %s address %s", ext_pcm_get_error(ext_pcm), out->bus_address); - restart = true; - } else { - ALOGV("pcm_write succeed address %s", out->bus_address); + if (write_error) { + ALOGE("pcm_write failed %s address %s", + ext_pcm_get_error(ext_pcm), out->bus_address); + restart = true; + } else { + ALOGV("pcm_write succeed address %s", out->bus_address); + } } } if (buffer) { @@ -402,8 +470,8 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer, si } if (frames_written < frames) { - ALOGW("Hardware backing HAL too slow, could only write %zu of %zu frames", - frames_written, frames); + ALOGW("%s Hardware backing HAL too slow, could only write %zu of %zu frames", + __func__, frames_written, frames); } /* Always consume all bytes */ @@ -641,28 +709,18 @@ static int in_dump(const struct audio_stream *stream, int fd) { static int in_set_parameters(struct audio_stream *stream, const char *kvpairs) { struct generic_stream_in *in = (struct generic_stream_in *)stream; struct str_parms *parms; - char value[32]; - int ret; - long val; - char *end; + int ret = 0; pthread_mutex_lock(&in->lock); if (!in->standby) { ret = -ENOSYS; } else { parms = str_parms_create_str(kvpairs); - - ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, - value, sizeof(value)); + int val = 0; + ret = get_int_value(parms, AUDIO_PARAMETER_STREAM_ROUTING, &val); if (ret >= 0) { - errno = 0; - val = strtol(value, &end, 10); - if ((errno == 0) && (end != NULL) && (*end == '\0') && ((int)val == val)) { - in->device = (int)val; - ret = 0; - } else { - ret = -EINVAL; - } + in->device = (int)val; + ret = 0; } str_parms_destroy(parms); @@ -740,14 +798,17 @@ static int in_standby(struct audio_stream *stream) { return 0; } -#define STEP (3.14159265 / 180) -// Generates pure tone for FM_TUNER -static int pseudo_pcm_read(void *data, unsigned int count) { - unsigned int length = count / sizeof(short); - short *sdata = (short *)data; +// Generates pure tone for FM_TUNER and bus_device +static int pseudo_pcm_read(void *data, unsigned int count, struct oscillator *oscillator) { + unsigned int length = count / sizeof(int16_t); + int16_t *sdata = (int16_t *)data; for (int index = 0; index < length; index++) { - sdata[index] = (short)(sin(index * STEP) * 4096); + sdata[index] = (int16_t)(sin(oscillator->phase) * 4096); + oscillator->phase += oscillator->phase_increment; + oscillator->phase = oscillator->phase > TWO_PI ? + oscillator->phase - TWO_PI : oscillator->phase; } + return count; } @@ -829,6 +890,15 @@ static void *in_read_worker(void *args) { return NULL; } +static bool address_has_tone_keyword(char * address) { + return strstr(address, TONE_ADDRESS_KEYWORD) != NULL; +} + +static bool is_tone_generator_device(struct generic_stream_in *in) { + return in->device == AUDIO_DEVICE_IN_FM_TUNER || ((in->device == AUDIO_DEVICE_IN_BUS) && + address_has_tone_keyword(in->bus_address)); +} + static ssize_t in_read(struct audio_stream_in *stream, void *buffer, size_t bytes) { struct generic_stream_in *in = (struct generic_stream_in *)stream; struct generic_audio_device *adev = in->dev; @@ -843,8 +913,9 @@ static ssize_t in_read(struct audio_stream_in *stream, void *buffer, size_t byte if (in->worker_standby) { in->worker_standby = false; } - // FM_TUNER fills the buffer via pseudo_pcm_read directly - if (in->device != AUDIO_DEVICE_IN_FM_TUNER) { + + // Tone generators fill the buffer via pseudo_pcm_read directly + if (!is_tone_generator_device(in)) { pthread_cond_signal(&in->worker_wake); } @@ -881,8 +952,8 @@ static ssize_t in_read(struct audio_stream_in *stream, void *buffer, size_t byte } in->standby_frames_read += frames; - if (in->device == AUDIO_DEVICE_IN_FM_TUNER) { - int read_bytes = pseudo_pcm_read(buffer, bytes); + if (is_tone_generator_device(in)) { + int read_bytes = pseudo_pcm_read(buffer, bytes, &in->oscillator); read_frames = read_bytes / audio_stream_in_frame_size(stream); } else if (popcount(in->req_config.channel_mask) == 1 && in->pcm_config.channels == 2) { @@ -1032,12 +1103,14 @@ static int adev_open_output_stream(struct audio_hw_device *dev, }; out->amplitude_ratio = 1.0; if (property_get_bool(PROP_KEY_SIMULATE_MULTI_ZONE_AUDIO, false)) { - out->enabled_channels = strstr(out->bus_address, "rear") + out->enabled_channels = strstr(out->bus_address, AUDIO_ZONE_KEYWORD) ? RIGHT_CHANNEL: LEFT_CHANNEL; + ALOGD("%s Routing %s to %s channel", __func__, + out->bus_address, out->enabled_channels == RIGHT_CHANNEL ? "Right" : "Left"); } } *stream_out = &out->stream; - ALOGD("%s bus:%s", __func__, out->bus_address); + ALOGD("%s bus: %s", __func__, out->bus_address); error: return ret; @@ -1067,10 +1140,22 @@ static void adev_close_output_stream(struct audio_hw_device *dev, } static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs) { - return 0; + struct generic_audio_device *adev = (struct generic_audio_device *)dev; + pthread_mutex_lock(&adev->lock); + struct str_parms *parms = str_parms_create_str(kvpairs); + int value = 0; + int results = get_int_value(parms, AAE_PARAMETER_KEY_FOR_SELECTED_ZONE, &value); + if (results >= 0) { + adev->last_zone_selected_to_play = value; + results = 0; + ALOGD("%s Changed play zone id to %d", __func__, adev->last_zone_selected_to_play); + } + str_parms_destroy(parms); + pthread_mutex_unlock(&adev->lock); + return results; } -static char *adev_get_parameters(const struct audio_hw_device *dev, const char *keys) { +static char *adev_get_parameters(const struct audio_hw_device * dev, const char *keys) { return NULL; } @@ -1160,6 +1245,25 @@ static void adev_close_input_stream(struct audio_hw_device *dev, free(stream); } +static void increase_next_tone_frequency(struct generic_audio_device *adev) { + adev->next_tone_frequency_to_assign += TONE_FREQUENCY_INCREASE; + if (adev->next_tone_frequency_to_assign > MAX_TONE_FREQUENCY) { + adev->next_tone_frequency_to_assign = DEFAULT_FREQUENCY; + } +} + +static int create_or_fetch_tone_frequency(struct generic_audio_device *adev, + char *address, int update_frequency) { + int *frequency = hashmapGet(adev->in_bus_tone_frequency_map, address); + if (frequency == NULL) { + frequency = calloc(1, sizeof(int)); + *frequency = update_frequency; + hashmapPut(adev->in_bus_tone_frequency_map, strdup(address), frequency); + ALOGD("%s assigned frequency %d to %s", __func__, *frequency, address); + } + return *frequency; +} + static int adev_open_input_stream(struct audio_hw_device *dev, audio_io_handle_t handle, audio_devices_t devices, struct audio_config *config, struct audio_stream_in **stream_in, audio_input_flags_t flags __unused, const char *address, @@ -1227,8 +1331,17 @@ static int adev_open_input_stream(struct audio_hw_device *dev, } if (address) { - in->bus_address = calloc(strlen(address) + 1, sizeof(char)); - strncpy(in->bus_address, address, strlen(address)); + in->bus_address = strdup(address); + if (is_tone_generator_device(in)) { + int update_frequency = adev->next_tone_frequency_to_assign; + int frequency = create_or_fetch_tone_frequency(adev, address, update_frequency); + if (update_frequency == frequency) { + increase_next_tone_frequency(adev); + } + in->oscillator.phase = 0.0f; + in->oscillator.phase_increment = (TWO_PI*(frequency)) + / ((float) in_get_sample_rate(&in->stream.common)); + } } *stream_in = &in->stream; @@ -1325,6 +1438,9 @@ static int adev_close(hw_device_t *dev) { if (adev->out_bus_stream_map) { hashmapFree(adev->out_bus_stream_map); } + if (adev->in_bus_tone_frequency_map) { + hashmapFree(adev->in_bus_tone_frequency_map); + } free(adev); } @@ -1404,6 +1520,8 @@ static int adev_open(const hw_module_t *module, *device = &adev->device.common; adev->mixer = mixer_open(PCM_CARD); + + ALOGD("%s Mixer name %s", __func__, mixer_get_name(adev->mixer)); struct mixer_ctl *ctl; // Set default mixer ctls @@ -1432,6 +1550,13 @@ static int adev_open(const hw_module_t *module, // Initialize the bus address to output stream map adev->out_bus_stream_map = hashmapCreate(5, str_hash_fn, str_eq); + // Initialize the bus address to input stream map + adev->in_bus_tone_frequency_map = hashmapCreate(5, str_hash_fn, str_eq); + + adev->next_tone_frequency_to_assign = DEFAULT_FREQUENCY; + + adev->last_zone_selected_to_play = DEFAULT_ZONE_TO_LEFT_SPEAKER; + audio_device_ref_count++; unlock: diff --git a/emulator/audio/driver/audio_hw.h b/emulator/audio/driver/audio_hw.h index 903a9b8..d195a53 100644 --- a/emulator/audio/driver/audio_hw.h +++ b/emulator/audio/driver/audio_hw.h @@ -33,6 +33,10 @@ struct generic_audio_device { bool mic_mute; // Protected by this->lock struct mixer *mixer; // Protected by this->lock Hashmap *out_bus_stream_map; // Extended field. Constant after init + Hashmap *in_bus_tone_frequency_map; // Extended field. Constant after init + int next_tone_frequency_to_assign; // Protected by this->lock + // Play on Speaker zone selection + int last_zone_selected_to_play; // Protected by this->lock }; enum output_channel_enable { @@ -70,6 +74,11 @@ struct generic_stream_out { bool worker_exit; // Protected by this->lock }; +struct oscillator { + float phase; + float phase_increment; +}; + struct generic_stream_in { struct audio_stream_in stream; // Constant after init pthread_mutex_t lock; @@ -94,6 +103,9 @@ struct generic_stream_in { pthread_cond_t worker_wake; // Protected by this->lock bool worker_standby; // Protected by this->lock bool worker_exit; // Protected by this->lock + + // Tone Oscillator + struct oscillator oscillator; // Protected by this->lock }; #endif // AUDIO_HW_H |