summaryrefslogtreecommitdiff
path: root/emulator/audio
diff options
context:
space:
mode:
Diffstat (limited to 'emulator/audio')
-rw-r--r--emulator/audio/audio_policy_configuration.xml121
-rw-r--r--emulator/audio/car_emulator_audio.mk1
-rw-r--r--emulator/audio/driver/Android.bp21
-rw-r--r--emulator/audio/driver/audio_extn/audio_extn.h38
-rw-r--r--emulator/audio/driver/audio_extn/hfp.c143
-rw-r--r--emulator/audio/driver/audio_hw.c68
-rw-r--r--emulator/audio/driver/audio_hw.h1
-rw-r--r--emulator/audio/driver/audio_vbuffer.c3
-rw-r--r--emulator/audio/driver/ext_pcm.c54
-rw-r--r--emulator/audio/driver/ext_pcm.h1
-rw-r--r--emulator/audio/halservice/android.hardware.audio.service-caremu.rc1
-rw-r--r--emulator/audio/halservice/service.cpp10
12 files changed, 364 insertions, 98 deletions
diff --git a/emulator/audio/audio_policy_configuration.xml b/emulator/audio/audio_policy_configuration.xml
index 4e61c76..d2a2b26 100644
--- a/emulator/audio/audio_policy_configuration.xml
+++ b/emulator/audio/audio_policy_configuration.xml
@@ -26,8 +26,8 @@
The module names are the same as in current .conf file:
“primary”, “A2DP”, “remote_submix”, “USB”
Each module will contain the following sections:
- “devicePorts”: a list of device descriptors for all input and output devices accessible via this
- module.
+ “devicePorts”: a list of device descriptors for all input and output devices accessible via
+ this module.
This contains both permanently attached devices and removable devices.
"gain": constraints applied to the millibel values:
- maxValueMB >= minValueMB
@@ -35,8 +35,8 @@
- (maxValueMB - minValueMB) % stepValueMB == 0
- (defaultValueMB - minValueMB) % stepValueMB == 0
“mixPorts”: listing all output and input streams exposed by the audio HAL
- “routes”: list of possible connections between input and output devices or between stream and
- devices.
+ “routes”: list of possible connections between input and output devices or between stream
+ and devices.
"route": is defined by an attribute:
-"type": <mux|mix> means all sources are mutual exclusive (mux) or can be mixed (mix)
-"sink": the sink involved in this route
@@ -60,7 +60,7 @@
<item>bus6_notification_out</item>
<item>bus7_system_sound_out</item>
<!-- names with _audio_zone_# are used for defined an emulator rear seat audio zone
- where each number # is the zone id number -->
+ 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>
@@ -73,7 +73,7 @@
<defaultOutputDevice>bus0_media_out</defaultOutputDevice>
<mixPorts>
<mixPort name="mixport_bus0_media_out" role="source"
- flags="AUDIO_OUTPUT_FLAG_PRIMARY">
+ flags="AUDIO_OUTPUT_FLAG_PRIMARY">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
samplingRates="48000"
channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
@@ -146,84 +146,93 @@
</mixPorts>
<devicePorts>
<devicePort tagName="bus0_media_out" role="sink" type="AUDIO_DEVICE_OUT_BUS"
- address="bus0_media_out">
+ address="bus0_media_out">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
- samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
<gains>
<gain name="" mode="AUDIO_GAIN_MODE_JOINT"
- minValueMB="-3200" maxValueMB="600" defaultValueMB="0" stepValueMB="100"/>
+ minValueMB="-3200" maxValueMB="600"
+ defaultValueMB="0" stepValueMB="100"/>
</gains>
</devicePort>
<devicePort tagName="bus1_navigation_out" role="sink" type="AUDIO_DEVICE_OUT_BUS"
address="bus1_navigation_out">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
- samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
<gains>
<gain name="" mode="AUDIO_GAIN_MODE_JOINT"
- minValueMB="-3200" maxValueMB="600" defaultValueMB="0" stepValueMB="100"/>
+ minValueMB="-3200" maxValueMB="600"
+ defaultValueMB="0" stepValueMB="100"/>
</gains>
</devicePort>
<devicePort tagName="bus2_voice_command_out" role="sink" type="AUDIO_DEVICE_OUT_BUS"
- address="bus2_voice_command_out">
+ address="bus2_voice_command_out">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
- samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
<gains>
<gain name="" mode="AUDIO_GAIN_MODE_JOINT"
- minValueMB="-3200" maxValueMB="600" defaultValueMB="0" stepValueMB="100"/>
+ minValueMB="-3200" maxValueMB="600"
+ defaultValueMB="0" stepValueMB="100"/>
</gains>
</devicePort>
<devicePort tagName="bus3_call_ring_out" role="sink" type="AUDIO_DEVICE_OUT_BUS"
- address="bus3_call_ring_out">
+ address="bus3_call_ring_out">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
- samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
<gains>
<gain name="" mode="AUDIO_GAIN_MODE_JOINT"
- minValueMB="-3200" maxValueMB="600" defaultValueMB="0" stepValueMB="100"/>
+ minValueMB="-3200" maxValueMB="600"
+ defaultValueMB="0" stepValueMB="100"/>
</gains>
</devicePort>
<devicePort tagName="bus4_call_out" role="sink" type="AUDIO_DEVICE_OUT_BUS"
- address="bus4_call_out">
+ address="bus4_call_out">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
- samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
<gains>
<gain name="" mode="AUDIO_GAIN_MODE_JOINT"
- minValueMB="-3200" maxValueMB="600" defaultValueMB="0" stepValueMB="100"/>
+ minValueMB="-3200" maxValueMB="600"
+ defaultValueMB="0" stepValueMB="100"/>
</gains>
</devicePort>
<devicePort tagName="bus5_alarm_out" role="sink" type="AUDIO_DEVICE_OUT_BUS"
- address="bus5_alarm_out">
+ address="bus5_alarm_out">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
- samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
<gains>
<gain name="" mode="AUDIO_GAIN_MODE_JOINT"
- minValueMB="-3200" maxValueMB="600" defaultValueMB="0" stepValueMB="100"/>
+ minValueMB="-3200" maxValueMB="600"
+ defaultValueMB="0" stepValueMB="100"/>
</gains>
</devicePort>
<devicePort tagName="bus6_notification_out" role="sink" type="AUDIO_DEVICE_OUT_BUS"
- address="bus6_notification_out">
+ address="bus6_notification_out">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
- samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
<gains>
<gain name="" mode="AUDIO_GAIN_MODE_JOINT"
- minValueMB="-3200" maxValueMB="600" defaultValueMB="0" stepValueMB="100"/>
+ minValueMB="-3200" maxValueMB="600"
+ defaultValueMB="0" stepValueMB="100"/>
</gains>
</devicePort>
<devicePort tagName="bus7_system_sound_out" role="sink" type="AUDIO_DEVICE_OUT_BUS"
- address="bus7_system_sound_out">
+ address="bus7_system_sound_out">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
- samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
<gains>
<gain name="" mode="AUDIO_GAIN_MODE_JOINT"
- minValueMB="-3200" maxValueMB="600" defaultValueMB="0" stepValueMB="100"/>
+ minValueMB="-3200" maxValueMB="600"
+ defaultValueMB="0" stepValueMB="100"/>
</gains>
</devicePort>
<devicePort tagName="bus100_audio_zone_1" role="sink" type="AUDIO_DEVICE_OUT_BUS"
- address="bus100_audio_zone_1">
+ address="bus100_audio_zone_1">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
- samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
<gains>
<gain name="" mode="AUDIO_GAIN_MODE_JOINT"
- minValueMB="-3200" maxValueMB="600" defaultValueMB="0" stepValueMB="100"/>
+ minValueMB="-3200" maxValueMB="600"
+ defaultValueMB="0" stepValueMB="100"/>
</gains>
</devicePort>
<devicePort tagName="bus200_audio_zone_2" role="sink" type="AUDIO_DEVICE_OUT_BUS"
@@ -232,31 +241,35 @@
samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
<gains>
<gain name="" mode="AUDIO_GAIN_MODE_JOINT"
- minValueMB="-3200" maxValueMB="600" defaultValueMB="0" stepValueMB="100"/>
+ minValueMB="-3200" maxValueMB="600"
+ defaultValueMB="0" stepValueMB="100"/>
</gains>
</devicePort>
- <devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source">
+ <devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source"
+ address="Built-In Mic" >
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
- samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
- channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
</devicePort>
- <devicePort tagName="Built-In Back Mic" type="AUDIO_DEVICE_IN_BACK_MIC" role="source">
+ <devicePort tagName="Built-In Back Mic" type="AUDIO_DEVICE_IN_BACK_MIC"
+ role="source" address="Built-In Back Mic">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
- samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
- channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
</devicePort>
- <devicePort tagName="Echo-Reference Mic" type="AUDIO_DEVICE_IN_ECHO_REFERENCE" role="source">
+ <devicePort tagName="Echo-Reference Mic" type="AUDIO_DEVICE_IN_ECHO_REFERENCE" role="source"
+ address="Echo-Reference Mic">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
- samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
- channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
</devicePort>
<devicePort tagName="FM Tuner" type="AUDIO_DEVICE_IN_FM_TUNER" role="source"
- address="tuner0">
+ address="tuner0">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
- samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
<gains>
<gain name="" mode="AUDIO_GAIN_MODE_JOINT"
- minValueMB="-3200" maxValueMB="600" defaultValueMB="0" stepValueMB="100"/>
+ minValueMB="-3200" maxValueMB="600" defaultValueMB="0" stepValueMB="100"/>
</gains>
</devicePort>
<devicePort tagName="Tone Generator 0" type="AUDIO_DEVICE_IN_BUS" role="source"
@@ -265,7 +278,8 @@
samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
<gains>
<gain name="" mode="AUDIO_GAIN_MODE_JOINT"
- minValueMB="-3200" maxValueMB="600" defaultValueMB="0" stepValueMB="100"/>
+ minValueMB="-3200" maxValueMB="600"
+ defaultValueMB="0" stepValueMB="100"/>
</gains>
</devicePort>
<devicePort tagName="Tone Generator 1" type="AUDIO_DEVICE_IN_BUS" role="source"
@@ -274,7 +288,8 @@
samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
<gains>
<gain name="" mode="AUDIO_GAIN_MODE_JOINT"
- minValueMB="-3200" maxValueMB="600" defaultValueMB="0" stepValueMB="100"/>
+ minValueMB="-3200" maxValueMB="600"
+ defaultValueMB="0" stepValueMB="100"/>
</gains>
</devicePort>
</devicePorts>
@@ -282,15 +297,19 @@
<routes>
<route type="mix" sink="bus0_media_out" sources="mixport_bus0_media_out"/>
<route type="mix" sink="bus1_navigation_out" sources="mixport_bus1_navigation_out"/>
- <route type="mix" sink="bus2_voice_command_out" sources="mixport_bus2_voice_command_out"/>
+ <route type="mix" sink="bus2_voice_command_out"
+ sources="mixport_bus2_voice_command_out"/>
<route type="mix" sink="bus3_call_ring_out" sources="mixport_bus3_call_ring_out"/>
<route type="mix" sink="bus4_call_out" sources="mixport_bus4_call_out"/>
<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="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_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="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"/>
diff --git a/emulator/audio/car_emulator_audio.mk b/emulator/audio/car_emulator_audio.mk
index 9ebb3b6..80e59f7 100644
--- a/emulator/audio/car_emulator_audio.mk
+++ b/emulator/audio/car_emulator_audio.mk
@@ -35,5 +35,6 @@ PRODUCT_COPY_FILES += \
frameworks/av/services/audiopolicy/config/default_volume_tables.xml:$(TARGET_COPY_OUT_VENDOR)/etc/default_volume_tables.xml \
device/generic/car/emulator/audio/audio_policy_configuration.xml:$(TARGET_COPY_OUT_VENDOR)/etc/audio_policy_configuration.xml \
device/generic/car/emulator/audio/car_audio_configuration.xml:$(TARGET_COPY_OUT_VENDOR)/etc/car_audio_configuration.xml \
+ frameworks/av/media/libeffects/data/audio_effects.xml:$(TARGET_COPY_OUT_VENDOR)/etc/audio_effects.xml \
DEVICE_PACKAGE_OVERLAYS += device/generic/car/emulator/audio/overlay
diff --git a/emulator/audio/driver/Android.bp b/emulator/audio/driver/Android.bp
index 945c628..8b9f53e 100644
--- a/emulator/audio/driver/Android.bp
+++ b/emulator/audio/driver/Android.bp
@@ -24,13 +24,31 @@ package {
default_applicable_licenses: ["device_generic_car_license"],
}
+soong_config_module_type {
+ name: "audio_extn_cc_defaults",
+ module_type: "cc_defaults",
+ config_namespace: "audio_extn_config",
+ bool_variables: ["isHFPEnabled"],
+ properties: ["srcs", "cflags"],
+}
+
+audio_extn_cc_defaults {
+ name: "audio_extn_hfp",
+ soong_config_variables: {
+ isHFPEnabled: {
+ cflags: ["-DHFP_ENABLED"],
+ srcs: ["audio_extn/hfp.c"],
+ },
+ },
+}
+
cc_library_shared {
vendor: true,
vintf_fragments: ["android.hardware.audio@6.0-impl.xml"],
name: "audio.primary.caremu",
relative_install_path: "hw",
-
+ defaults: ["audio_extn_hfp"],
srcs: [
"audio_hw.c",
"audio_vbuffer.c",
@@ -38,6 +56,7 @@ cc_library_shared {
],
include_dirs: ["external/tinyalsa/include"],
+ local_include_dirs: ["audio_extn"],
export_include_dirs: [
"include"
],
diff --git a/emulator/audio/driver/audio_extn/audio_extn.h b/emulator/audio/driver/audio_extn/audio_extn.h
new file mode 100644
index 0000000..13050c6
--- /dev/null
+++ b/emulator/audio/driver/audio_extn/audio_extn.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 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_EXTN_H
+#define AUDIO_EXTN_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "audio_hw.h"
+#include <cutils/str_parms.h>
+
+#ifndef HFP_ENABLED
+#define audio_extn_hfp_set_parameters(adev, parms) (0)
+#else
+int audio_extn_hfp_set_parameters(struct generic_audio_device *adev,
+ struct str_parms *parms);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AUDIO_EXTN_H */
diff --git a/emulator/audio/driver/audio_extn/hfp.c b/emulator/audio/driver/audio_extn/hfp.c
new file mode 100644
index 0000000..fbe4000
--- /dev/null
+++ b/emulator/audio/driver/audio_extn/hfp.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+#ifdef HFP_ENABLED
+
+#define LOG_TAG "audio_hw_hfp"
+#define LOG_NDDEBUG 0
+
+#include "audio_extn.h"
+#include <cutils/log.h>
+#include <cutils/str_parms.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#define AUDIO_PARAMETER_HFP_ENABLE "hfp_enable"
+#define AUDIO_PARAMETER_HFP_SET_SAMPLING_RATE "hfp_set_sampling_rate"
+#define AUDIO_PARAMETER_HFP_VOLUME "hfp_volume"
+#define AUDIO_PARAMETER_HFP_VALUE_MAX 128
+
+static int hfp_set_enable(struct generic_audio_device *adev, bool enable) {
+ struct mixer_ctl *ctl;
+ ALOGD("%s: enter enable : %d", __func__, enable);
+
+ ctl = mixer_get_ctl_by_name(adev->mixer, AUDIO_PARAMETER_HFP_ENABLE);
+ if (!ctl) {
+ ALOGE("%s: Could not get mixer ctl for - %s", __func__,
+ AUDIO_PARAMETER_HFP_ENABLE);
+ return -EINVAL;
+ }
+
+ if (mixer_ctl_set_value(ctl, 0, enable) < 0) {
+ ALOGE("%s: Couldn't set mixer ctrl for %s", __func__,
+ AUDIO_PARAMETER_HFP_ENABLE);
+ return -EINVAL;
+ }
+
+ adev->hfp_running = enable;
+ ALOGD("%s: exit: status success", __func__);
+ return 0;
+}
+
+static int hfp_set_sampling_rate(struct generic_audio_device *adev, int rate) {
+ struct mixer_ctl *ctl;
+ ALOGD("%s: enter rate = %d", __func__, rate);
+
+ ctl =
+ mixer_get_ctl_by_name(adev->mixer, AUDIO_PARAMETER_HFP_SET_SAMPLING_RATE);
+ if (!ctl) {
+ ALOGE("%s: Could not get mixer ctl for - %s", __func__,
+ AUDIO_PARAMETER_HFP_SET_SAMPLING_RATE);
+ return -EINVAL;
+ }
+
+ if (mixer_ctl_set_value(ctl, 0, rate) < 0) {
+ ALOGE("%s: Couldn't set mixer ctrl for %s", __func__,
+ AUDIO_PARAMETER_HFP_SET_SAMPLING_RATE);
+ return -EINVAL;
+ }
+
+ ALOGD("%s: exit: status success", __func__);
+ return 0;
+}
+
+static int hfp_set_volume(struct generic_audio_device *adev, int vol) {
+ struct mixer_ctl *ctl;
+ ALOGD("%s: enter vol = %d", __func__, vol);
+
+ ctl = mixer_get_ctl_by_name(adev->mixer, AUDIO_PARAMETER_HFP_VOLUME);
+ if (!ctl) {
+ ALOGE("%s: Could not get mixer ctl for - %s", __func__,
+ AUDIO_PARAMETER_HFP_VOLUME);
+ return -EINVAL;
+ }
+
+ if (mixer_ctl_set_value(ctl, 0, vol) < 0) {
+ ALOGE("%s: Couldn't set mixer ctrl for %s", __func__,
+ AUDIO_PARAMETER_HFP_VOLUME);
+ return -EINVAL;
+ }
+
+ ALOGD("%s: exit: status success", __func__);
+ return 0;
+}
+
+int audio_extn_hfp_set_parameters(struct generic_audio_device *adev,
+ struct str_parms *parms) {
+ int ret = 0, rate, vol;
+ char value[AUDIO_PARAMETER_HFP_VALUE_MAX] = {0};
+
+ ret = str_parms_get_str(parms, AUDIO_PARAMETER_HFP_ENABLE, value,
+ sizeof(value));
+ if (ret >= 0) {
+ if (!strncmp(value, "true", sizeof(value))) {
+ if (!adev->hfp_running)
+ ret = hfp_set_enable(adev, true);
+ else
+ ALOGW("%s: HFP is already active.", __func__);
+ } else {
+ if (adev->hfp_running)
+ ret = hfp_set_enable(adev, false);
+ else
+ ALOGW("%s: ignore STOP, HFP not active", __func__);
+ }
+
+ if (ret < 0)
+ goto exit;
+ }
+
+ memset(value, 0, sizeof(value));
+ ret = str_parms_get_str(parms, AUDIO_PARAMETER_HFP_SET_SAMPLING_RATE, value,
+ sizeof(value));
+ if (ret >= 0) {
+ rate = strtol(value, NULL, 10);
+ ret = hfp_set_sampling_rate(adev, rate);
+ if (ret < 0)
+ goto exit;
+ }
+
+ memset(value, 0, sizeof(value));
+ ret = str_parms_get_str(parms, AUDIO_PARAMETER_HFP_VOLUME, value,
+ sizeof(value));
+ if (ret >= 0) {
+ vol = strtol(value, NULL, 10);
+ ret = hfp_set_volume(adev, vol);
+ }
+
+exit:
+ ALOGD("%s exit: status", __func__);
+ return ret;
+}
+#endif /*HFP_ENABLED*/
diff --git a/emulator/audio/driver/audio_hw.c b/emulator/audio/driver/audio_hw.c
index 36796c4..65cbb11 100644
--- a/emulator/audio/driver/audio_hw.c
+++ b/emulator/audio/driver/audio_hw.c
@@ -22,6 +22,7 @@
#define LOG_TAG "audio_hw_generic_caremu"
// #define LOG_NDEBUG 0
+#include "audio_extn.h"
#include "audio_hw.h"
#include "include/audio_hw_control.h"
@@ -87,6 +88,7 @@ static const char * const AUDIO_ZONE_KEYWORD = "_audio_zone_";
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
#define SIZE_OF_PARSE_BUFFER 32
+#define SIZE_OF_THREAD_NAME_BUFFER 16
static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state);
@@ -162,6 +164,11 @@ void set_device_address_is_muted(const char *device_address, bool is_muted){
pthread_mutex_unlock(&out->lock);
}
+static void set_shortened_thread_name(pthread_t thread, const char *name) {
+ char shortenedName[SIZE_OF_THREAD_NAME_BUFFER];
+ strncpy(shortenedName, name, SIZE_OF_THREAD_NAME_BUFFER);
+ pthread_setname_np(thread, shortenedName);
+}
static struct pcm_config pcm_config_out = {
.channels = 2,
@@ -505,6 +512,8 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer, si
const size_t frame_size = audio_stream_out_frame_size(stream);
const size_t frames = bytes / frame_size;
+ set_shortened_thread_name(pthread_self(), __func__);
+
pthread_mutex_lock(&out->lock);
if (out->worker_standby) {
@@ -1002,6 +1011,8 @@ static ssize_t in_read(struct audio_stream_in *stream, void *buffer, size_t byte
bool mic_mute = false;
size_t read_bytes = 0;
+ set_shortened_thread_name(pthread_self(), __func__);
+
adev_get_mic_mute(&adev->device, &mic_mute);
pthread_mutex_lock(&in->lock);
@@ -1183,34 +1194,35 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
out->worker_standby = true;
out->worker_exit = false;
pthread_create(&out->worker_thread, NULL, out_write_worker, out);
- }
-
- out->enabled_channels = BOTH_CHANNELS;
- // For targets where output streams are closed regularly, currently ducked/muted addresses
- // should be tracked so that the address of new streams can be checked to determine the
- // default state
- out->is_ducked = 0;
- out->is_muted = 0;
- if (address) {
- out->bus_address = calloc(strlen(address) + 1, sizeof(char));
- strncpy(out->bus_address, address, strlen(address));
- hashmapPut(adev->out_bus_stream_map, out->bus_address, out);
- /* TODO: read struct audio_gain from audio_policy_configuration */
- out->gain_stage = (struct audio_gain) {
- .min_value = -3200,
- .max_value = 600,
- .step_value = 100,
- };
- out->amplitude_ratio = 1.0;
- if (property_get_bool(PROP_KEY_SIMULATE_MULTI_ZONE_AUDIO, false)) {
- 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");
+ set_shortened_thread_name(out->worker_thread, address);
+
+ out->enabled_channels = BOTH_CHANNELS;
+ // For targets where output streams are closed regularly, currently ducked/muted addresses
+ // should be tracked so that the address of new streams can be checked to determine the
+ // default state
+ out->is_ducked = 0;
+ out->is_muted = 0;
+ if (address) {
+ out->bus_address = calloc(strlen(address) + 1, sizeof(char));
+ strncpy(out->bus_address, address, strlen(address));
+ hashmapPut(adev->out_bus_stream_map, out->bus_address, out);
+ /* TODO: read struct audio_gain from audio_policy_configuration */
+ out->gain_stage = (struct audio_gain) {
+ .min_value = -3200,
+ .max_value = 600,
+ .step_value = 100,
+ };
+ out->amplitude_ratio = 1.0;
+ if (property_get_bool(PROP_KEY_SIMULATE_MULTI_ZONE_AUDIO, false)) {
+ 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);
}
- *stream_out = &out->stream;
- ALOGD("%s bus: %s", __func__, out->bus_address);
error:
return ret;
@@ -1250,6 +1262,7 @@ static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
results = 0;
ALOGD("%s Changed play zone id to %d", __func__, adev->last_zone_selected_to_play);
}
+ results = audio_extn_hfp_set_parameters(adev, parms);
str_parms_destroy(parms);
pthread_mutex_unlock(&adev->lock);
return results;
@@ -1428,6 +1441,7 @@ static int adev_open_input_stream(struct audio_hw_device *dev,
in->worker_standby = true;
in->worker_exit = false;
pthread_create(&in->worker_thread, NULL, in_read_worker, in);
+ set_shortened_thread_name(in->worker_thread, address ? address : "mic");
}
if (address) {
@@ -1665,6 +1679,8 @@ static int adev_open(const hw_module_t *module,
adev->last_zone_selected_to_play = DEFAULT_ZONE_TO_LEFT_SPEAKER;
+ adev->hfp_running = false;
+
device_handle = adev;
audio_device_ref_count++;
diff --git a/emulator/audio/driver/audio_hw.h b/emulator/audio/driver/audio_hw.h
index 1f9aa51..c243222 100644
--- a/emulator/audio/driver/audio_hw.h
+++ b/emulator/audio/driver/audio_hw.h
@@ -37,6 +37,7 @@ struct generic_audio_device {
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
+ bool hfp_running;
};
static struct generic_audio_device *device_handle;
diff --git a/emulator/audio/driver/audio_vbuffer.c b/emulator/audio/driver/audio_vbuffer.c
index 79be545..8377f5c 100644
--- a/emulator/audio/driver/audio_vbuffer.c
+++ b/emulator/audio/driver/audio_vbuffer.c
@@ -14,7 +14,8 @@
* limitations under the License.
*/
-#define LOG_TAG "audio_hw_generic"
+#define LOG_TAG "audio_hw_generic_caremu"
+// #define LOG_NDEBUG 0
#include <errno.h>
#include <stdlib.h>
diff --git a/emulator/audio/driver/ext_pcm.c b/emulator/audio/driver/ext_pcm.c
index df3e1f1..2b0e825 100644
--- a/emulator/audio/driver/ext_pcm.c
+++ b/emulator/audio/driver/ext_pcm.c
@@ -14,9 +14,11 @@
* limitations under the License.
*/
-#define LOG_TAG "audio_hw_generic"
+#define LOG_TAG "audio_hw_generic_caremu"
+// #define LOG_NDEBUG 0
#include <errno.h>
+#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -31,6 +33,8 @@ static struct ext_pcm *shared_ext_pcm = NULL;
// Sleep 10ms between each mixing, this interval value is arbitrary chosen
#define MIXER_INTERVAL_MS 10
+#define MS_TO_US 1000
+
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
@@ -70,7 +74,8 @@ static bool mixer_thread_mix(__unused void *key, void *value, void *context) {
}
static void *mixer_thread_loop(void *context) {
- ALOGD("%s: __enter__", __func__);
+ pthread_setname_np(pthread_self(), "car_mixer_loop");
+ ALOGD("%s: starting mixer loop", __func__);
struct ext_pcm *ext_pcm = (struct ext_pcm *)context;
do {
pthread_mutex_lock(&ext_pcm->mixer_lock);
@@ -79,14 +84,25 @@ static void *mixer_thread_loop(void *context) {
hashmapForEach(ext_pcm->mixer_pipeline_map, mixer_thread_mix,
&ext_pcm->mixer_pipeline);
if (ext_pcm->mixer_pipeline.position > 0) {
- pcm_write(ext_pcm->pcm, (void *)ext_pcm->mixer_pipeline.buffer,
+ int ret = pcm_write(ext_pcm->pcm, (void *)ext_pcm->mixer_pipeline.buffer,
ext_pcm->mixer_pipeline.position * sizeof(int16_t));
+ if (ret != 0) {
+ ALOGE("%s error[%d] writing data to pcm");
+ }
}
memset(&ext_pcm->mixer_pipeline, 0, sizeof(struct ext_mixer_pipeline));
pthread_cond_broadcast(&ext_pcm->mixer_wake);
pthread_mutex_unlock(&ext_pcm->mixer_lock);
- usleep(MIXER_INTERVAL_MS * 1000);
+ pthread_mutex_lock(&ext_pcm_init_lock);
+ bool keep_running = ext_pcm->run_mixer;
+ pthread_mutex_unlock(&ext_pcm_init_lock);
+ if (!keep_running) {
+ break;
+ }
+ usleep(MIXER_INTERVAL_MS * MS_TO_US);
} while (1);
+ ALOGD("%s: exiting mixer loop", __func__);
+ return NULL;
}
static int mixer_pipeline_write(struct ext_pcm *ext_pcm, const char *bus_address,
@@ -130,12 +146,10 @@ struct ext_pcm *ext_pcm_open(unsigned int card, unsigned int device,
pthread_create(&shared_ext_pcm->mixer_thread, (const pthread_attr_t *)NULL,
mixer_thread_loop, shared_ext_pcm);
shared_ext_pcm->mixer_pipeline_map = hashmapCreate(8, str_hash_fn, str_eq);
+ shared_ext_pcm->run_mixer = true;
}
- pthread_mutex_unlock(&ext_pcm_init_lock);
-
- pthread_mutex_lock(&shared_ext_pcm->lock);
shared_ext_pcm->ref_count += 1;
- pthread_mutex_unlock(&shared_ext_pcm->lock);
+ pthread_mutex_unlock(&ext_pcm_init_lock);
return shared_ext_pcm;
}
@@ -147,27 +161,37 @@ static bool mixer_free_pipeline(__unused void *key, void *value, void *context)
}
int ext_pcm_close(struct ext_pcm *ext_pcm) {
+ ALOGD("%s closing pcm", __func__);
if (ext_pcm == NULL || ext_pcm->pcm == NULL) {
return -EINVAL;
}
- pthread_mutex_lock(&ext_pcm->lock);
- ext_pcm->ref_count -= 1;
- pthread_mutex_unlock(&ext_pcm->lock);
-
pthread_mutex_lock(&ext_pcm_init_lock);
- if (ext_pcm->ref_count <= 0) {
+ int count = ext_pcm->ref_count -= 1;
+ if (count <= 0) {
+ ext_pcm->run_mixer = false;
+ // On pcm open new shared_ext_pcm will be created
+ shared_ext_pcm = NULL;
+ pthread_mutex_unlock(&ext_pcm_init_lock);
+ void* ret_val = NULL;
+ int ret = pthread_join(ext_pcm->mixer_thread, &ret_val);
+ if (ret != 0) {
+ ALOGE("%s error[%d] when joining thread",
+ __func__, ret);
+ // Try killing if timeout failed
+ pthread_kill(ext_pcm->mixer_thread, SIGINT);
+ }
+ pthread_mutex_lock(&ext_pcm_init_lock);
pthread_mutex_destroy(&ext_pcm->lock);
pcm_close(ext_pcm->pcm);
pthread_mutex_destroy(&ext_pcm->mixer_lock);
hashmapForEach(ext_pcm->mixer_pipeline_map, mixer_free_pipeline,
(void *)NULL);
hashmapFree(ext_pcm->mixer_pipeline_map);
- pthread_kill(ext_pcm->mixer_thread, SIGINT);
free(ext_pcm);
- shared_ext_pcm = NULL;
}
pthread_mutex_unlock(&ext_pcm_init_lock);
+ ALOGD("%s finished closing pcm", __func__);
return 0;
}
diff --git a/emulator/audio/driver/ext_pcm.h b/emulator/audio/driver/ext_pcm.h
index c038b86..562b874 100644
--- a/emulator/audio/driver/ext_pcm.h
+++ b/emulator/audio/driver/ext_pcm.h
@@ -34,6 +34,7 @@ struct ext_pcm {
struct pcm *pcm;
pthread_mutex_t lock;
pthread_cond_t mixer_wake;
+ bool run_mixer;
unsigned int ref_count;
pthread_mutex_t mixer_lock;
struct ext_mixer_pipeline mixer_pipeline;
diff --git a/emulator/audio/halservice/android.hardware.audio.service-caremu.rc b/emulator/audio/halservice/android.hardware.audio.service-caremu.rc
index 768425f..76ee350 100644
--- a/emulator/audio/halservice/android.hardware.audio.service-caremu.rc
+++ b/emulator/audio/halservice/android.hardware.audio.service-caremu.rc
@@ -7,4 +7,3 @@ service vendor.audio-hal /vendor/bin/hw/android.hardware.audio.service-caremu
capabilities BLOCK_SUSPEND
ioprio rt 4
task_profiles ProcessCapacityHigh HighPerformance
- onrestart restart audioserver
diff --git a/emulator/audio/halservice/service.cpp b/emulator/audio/halservice/service.cpp
index aafff4d..581e9af 100644
--- a/emulator/audio/halservice/service.cpp
+++ b/emulator/audio/halservice/service.cpp
@@ -47,6 +47,7 @@ using android::hardware::registerPassthroughServiceImplementation;
int main(int /* argc */, char* /* argv */ []) {
// Setup HIDL Audio HAL
+ LOG(INFO) << "AudioControl start audio HAL.";
configureRpcThreadpool(16, false /*callerWillJoin*/);
android::status_t status;
status = registerPassthroughServiceImplementation<IDevicesFactory>();
@@ -55,14 +56,17 @@ int main(int /* argc */, char* /* argv */ []) {
LOG_ALWAYS_FATAL_IF(status != OK, "Error while registering audio effects service: %d", status);
// Setup AudioControl HAL
- ABinderProcess_setThreadPoolMaxThreadCount(0);
+ ABinderProcess_setThreadPoolMaxThreadCount(16);
std::shared_ptr<AudioControl> audioControl = ::ndk::SharedRefBase::make<AudioControl>();
const std::string instance = std::string() + AudioControl::descriptor + "/default";
- binder_status_t aidlStatus =
- AServiceManager_addService(audioControl->asBinder().get(), instance.c_str());
+ binder_status_t aidlStatus = AServiceManager_addService(audioControl->asBinder().get(),
+ instance.c_str());
CHECK(aidlStatus == STATUS_OK);
+ LOG(INFO) << "AudioControl status: status " << aidlStatus;
+
ABinderProcess_joinThreadPool();
+ LOG(ERROR) << "ABinderProcess_joinThreadPool should never get here ";
return EXIT_FAILURE; // should not reach
}