From 74a845f8c4885a37593299c54043ef061c280ec0 Mon Sep 17 00:00:00 2001 From: jiabin Date: Wed, 5 Jan 2022 19:06:30 +0000 Subject: [PATCH 1/8] Set standby as false when the stream is started successfully. When the audio patch is created and the stream is started, set the standby as false. In that case, if there is a simultaneous request for read or write data, it is no need to start the stream again. Bug: 212509560 Test: repo steps in the bug Change-Id: Ic3dbab3134bc761271b6b2ac8619135ef08075bc --- modules/usbaudio/audio_hal.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/modules/usbaudio/audio_hal.c b/modules/usbaudio/audio_hal.c index fe921d69..616c4a62 100644 --- a/modules/usbaudio/audio_hal.c +++ b/modules/usbaudio/audio_hal.c @@ -1723,10 +1723,16 @@ static int adev_create_audio_patch(struct audio_hw_device *dev, if (!wasStandby) { device_lock(adev); if (in != NULL) { - start_input_stream(in); + ret = start_input_stream(in); + if (!ret) { + in->standby = false; + } } if (out != NULL) { - start_output_stream(out); + ret = start_output_stream(out); + if (!ret) { + out->standby = false; + } } device_unlock(adev); } From 7aad531bc9b0b4b52d353ddf9a172dcff1ab4c20 Mon Sep 17 00:00:00 2001 From: Brian Duddie Date: Wed, 7 Sep 2022 19:34:47 +0000 Subject: [PATCH 2/8] dynamic_sensor: Improve error logging Correctly pass errno to strerror() rather than the return value, which will always be -1 on error. Fixes: 245585769 Test: build only Change-Id: Iae1170949f3b2a0286ef8b9ddf26c74a6cee6783 --- modules/sensors/dynamic_sensor/HidRawDevice.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/sensors/dynamic_sensor/HidRawDevice.cpp b/modules/sensors/dynamic_sensor/HidRawDevice.cpp index 2588483a..6032ed95 100644 --- a/modules/sensors/dynamic_sensor/HidRawDevice.cpp +++ b/modules/sensors/dynamic_sensor/HidRawDevice.cpp @@ -204,7 +204,7 @@ bool HidRawDevice::getFeature(uint8_t id, std::vector *out) { int res = ::ioctl(mDevFd, HIDIOCGFEATURE(size), mIoBuffer.data()); if (res < 0) { LOG_E << "HidRawDevice::getFeature: feature " << static_cast(id) - << " ioctl returns " << res << " (" << ::strerror(res) << ")" << LOG_ENDL; + << " ioctl returned " << res << ", errno: " << ::strerror(errno) << LOG_ENDL; return false; } @@ -249,8 +249,8 @@ bool HidRawDevice::setFeature(uint8_t id, const std::vector &in) { std::copy(in.begin(), in.end(), &mIoBuffer[1]); int res = ::ioctl(mDevFd, HIDIOCSFEATURE(size), mIoBuffer.data()); if (res < 0) { - LOG_E << "HidRawDevice::setFeature: feature " << id << " ioctl returns " << res - << " (" << ::strerror(res) << ")" << LOG_ENDL; + LOG_E << "HidRawDevice::setFeature: feature " << id << " ioctl returned " << res + << ", errno: " << ::strerror(errno) << LOG_ENDL; return false; } return true; @@ -287,8 +287,8 @@ bool HidRawDevice::sendReport(uint8_t id, std::vector &data) { res = ::write(mDevFd, data.data(), size); } if (res < 0) { - LOG_E << "HidRawDevice::sendReport: output " << id << " write returns " << res - << " (" << ::strerror(res) << ")" << LOG_ENDL; + LOG_E << "HidRawDevice::sendReport: output " << id << " write returned " + << res << ", errno: " << ::strerror(errno) << LOG_ENDL; return false; } return true; @@ -302,8 +302,8 @@ bool HidRawDevice::receiveReport(uint8_t *id, std::vector *data) { uint8_t buffer[256]; int res = ::read(mDevFd, buffer, 256); if (res < 0) { - LOG_E << "HidRawDevice::receiveReport: read returns " << res - << " (" << ::strerror(res) << ")" << LOG_ENDL; + LOG_E << "HidRawDevice::receiveReport: read returned " << res + << ", errno: " << ::strerror(errno) << LOG_ENDL; return false; } From 46fd7e6077c4380ee65d136bd312782a306e1314 Mon Sep 17 00:00:00 2001 From: Theodore Dubois Date: Mon, 12 Dec 2022 10:49:08 -0800 Subject: [PATCH 3/8] Support HAL_PIXEL_FORMAT_BLOB in default gralloc Test: manual, ran scrcpy with codec2's blob allocator Change-Id: I647ed5b0e9df4920e4a02686185956aa71ee806e --- modules/gralloc/gralloc.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/gralloc/gralloc.cpp b/modules/gralloc/gralloc.cpp index 87bda975..f7ea01cf 100644 --- a/modules/gralloc/gralloc.cpp +++ b/modules/gralloc/gralloc.cpp @@ -224,7 +224,11 @@ static int gralloc_alloc(alloc_device_t* dev, case HAL_PIXEL_FORMAT_RAW16: bytesPerPixel = 2; break; + case HAL_PIXEL_FORMAT_BLOB: + bytesPerPixel = 1; + break; default: + ALOGE("gralloc_alloc bad format %d", format); return -EINVAL; } From c5782cba4a6af3b85c7e7f1af2bbbe06d7e9b13d Mon Sep 17 00:00:00 2001 From: jiabin Date: Thu, 15 Dec 2022 21:54:59 +0000 Subject: [PATCH 4/8] Add volume control for AOSP USB audio HAL. When the stream is open with bit-perfect output flag, the volume command may be sent to the HAL. Use volume control from the mixer when it is present. Bug: 262581771 Test: adjust volume Change-Id: I11e76450a2c3dbcad0ddbd56bd3db1ea83f10f2b --- modules/usbaudio/audio_hal.c | 96 +++++++++++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) diff --git a/modules/usbaudio/audio_hal.c b/modules/usbaudio/audio_hal.c index 616c4a62..6bf6b0d8 100644 --- a/modules/usbaudio/audio_hal.c +++ b/modules/usbaudio/audio_hal.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -118,6 +119,13 @@ struct stream_out { audio_io_handle_t handle; // Unique constant for a stream audio_patch_handle_t patch_handle; // Patch handle for this stream + + // Mixer information used for volume handling + struct mixer* mixer; + struct mixer_ctl* volume_ctl; + int volume_ctl_num_values; + int max_volume_level; + int min_volume_level; }; struct stream_in { @@ -223,6 +231,14 @@ static const audio_channel_mask_t CHANNEL_INDEX_MASKS_MAP[FCC_24 + 1] = { }; static const int CHANNEL_INDEX_MASKS_SIZE = AUDIO_ARRAY_SIZE(CHANNEL_INDEX_MASKS_MAP); +static const char* ALL_VOLUME_CONTROL_NAMES[] = { + "PCM Playback Volume", + "Headset Playback Volume", + "Headphone Playback Volume", + "Master Playback Volume", +}; +static const int VOLUME_CONTROL_NAMES_NUM = AUDIO_ARRAY_SIZE(ALL_VOLUME_CONTROL_NAMES); + /* * Locking Helpers */ @@ -495,6 +511,45 @@ static bool are_devices_the_same(unsigned int left_num_devices, left_num_devices, left_cards, left_devices); } +static void out_stream_find_mixer_volume_control(struct stream_out* out, int card) { + out->mixer = mixer_open(card); + if (out->mixer == NULL) { + ALOGI("%s, no mixer found for card=%d", __func__, card); + return; + } + unsigned int num_ctls = mixer_get_num_ctls(out->mixer); + for (int i = 0; i < VOLUME_CONTROL_NAMES_NUM; ++i) { + for (unsigned int j = 0; j < num_ctls; ++j) { + struct mixer_ctl *ctl = mixer_get_ctl(out->mixer, j); + enum mixer_ctl_type ctl_type = mixer_ctl_get_type(ctl); + if (strcasestr(mixer_ctl_get_name(ctl), ALL_VOLUME_CONTROL_NAMES[i]) == NULL || + ctl_type != MIXER_CTL_TYPE_INT) { + continue; + } + ALOGD("%s, mixer volume control(%s) found", __func__, ALL_VOLUME_CONTROL_NAMES[i]); + out->volume_ctl_num_values = mixer_ctl_get_num_values(ctl); + if (out->volume_ctl_num_values <= 0) { + ALOGE("%s the num(%d) of volume ctl values is wrong", + __func__, out->volume_ctl_num_values); + out->volume_ctl_num_values = 0; + continue; + } + out->max_volume_level = mixer_ctl_get_range_max(ctl); + out->min_volume_level = mixer_ctl_get_range_min(ctl); + if (out->max_volume_level < out->min_volume_level) { + ALOGE("%s the max volume level(%d) is less than min volume level(%d)", + __func__, out->max_volume_level, out->min_volume_level); + out->max_volume_level = 0; + out->min_volume_level = 0; + continue; + } + out->volume_ctl = ctl; + return; + } + } + ALOGI("%s, no volume control found", __func__); +} + /* * HAl Functions */ @@ -709,7 +764,31 @@ static uint32_t out_get_latency(const struct audio_stream_out *stream) static int out_set_volume(struct audio_stream_out *stream, float left, float right) { - return -ENOSYS; + struct stream_out *out = (struct stream_out *)stream; + int result = -ENOSYS; + stream_lock(&out->lock); + if (out->volume_ctl != NULL) { + int left_volume = + out->min_volume_level + ceil((out->max_volume_level - out->min_volume_level) * left); + int right_volume = + out->min_volume_level + ceil((out->max_volume_level - out->min_volume_level) * right); + int volumes[out->volume_ctl_num_values]; + if (out->volume_ctl_num_values == 1) { + volumes[0] = left_volume; + } else { + volumes[0] = left_volume; + volumes[1] = right_volume; + for (int i = 2; i < out->volume_ctl_num_values; ++i) { + volumes[i] = left_volume; + } + } + result = mixer_ctl_set_array(out->volume_ctl, volumes, out->volume_ctl_num_values); + if (result != 0) { + ALOGE("%s error=%d left=%f right=%f", __func__, result, left, right); + } + } + stream_unlock(&out->lock); + return result; } /* must be called with hw device and output stream mutexes locked */ @@ -965,6 +1044,10 @@ static int adev_open_output_stream(struct audio_hw_device *hw_dev, list_add_tail(&out->alsa_devices, &device_info->list_node); + if ((flags & AUDIO_OUTPUT_FLAG_BIT_PERFECT) != AUDIO_OUTPUT_FLAG_NONE) { + out_stream_find_mixer_volume_control(out, device_info->profile.card); + } + /* TODO The retry mechanism isn't implemented in AudioPolicyManager/AudioFlinger * So clear any errors that may have occurred above. */ @@ -998,6 +1081,17 @@ static void adev_close_output_stream(struct audio_hw_device *hw_dev, out->conversion_buffer = NULL; out->conversion_buffer_size = 0; + if (out->volume_ctl != NULL) { + for (int i = 0; i < out->volume_ctl_num_values; ++i) { + mixer_ctl_set_value(out->volume_ctl, i, out->max_volume_level); + } + out->volume_ctl = NULL; + } + if (out->mixer != NULL) { + mixer_close(out->mixer); + out->mixer = NULL; + } + device_lock(out->adev); list_remove(&out->list_node); out->adev->device_sample_rate = 0; From 662fe4aedae8ef10b3e8e48ab3f734ca101aa34d Mon Sep 17 00:00:00 2001 From: jiabin Date: Mon, 19 Dec 2022 19:31:36 +0000 Subject: [PATCH 5/8] Support opening bit-perfect output stream. When opening bit-perfect output stream, the HAL should require the HAL configuration match the request exactly. Bug: 262581771 Test: manually Change-Id: I2f79d41ad42b0c662d28667bde6ae115575d41e1 --- modules/usbaudio/audio_hal.c | 54 ++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/modules/usbaudio/audio_hal.c b/modules/usbaudio/audio_hal.c index 6bf6b0d8..43f8d240 100644 --- a/modules/usbaudio/audio_hal.c +++ b/modules/usbaudio/audio_hal.c @@ -120,6 +120,8 @@ struct stream_out { audio_patch_handle_t patch_handle; // Patch handle for this stream + bool is_bit_perfect; // True if the stream is open with bit-perfect output flag + // Mixer information used for volume handling struct mixer* mixer; struct mixer_ctl* volume_ctl; @@ -599,7 +601,8 @@ static int stream_set_new_devices(struct pcm_config *config, unsigned int num_devices, const int cards[], const int devices[], - int direction) + int direction, + bool is_bit_perfect) { int status = 0; stream_clear_devices(alsa_devices); @@ -616,7 +619,7 @@ static int stream_set_new_devices(struct pcm_config *config, __func__, cards[i], devices[i]); goto exit; } - status = proxy_prepare(&device_info->proxy, &device_info->profile, config); + status = proxy_prepare(&device_info->proxy, &device_info->profile, config, is_bit_perfect); if (status != 0) { ALOGE("%s failed to prepare device card=%d;device=%d", __func__, cards[i], devices[i]); @@ -926,6 +929,16 @@ static int adev_open_output_stream(struct audio_hw_device *hw_dev, ALOGV("adev_open_output_stream() handle:0x%X, devicesSpec:0x%X, flags:0x%X, addr:%s", handle, devicesSpec, flags, address); + const bool is_bit_perfect = ((flags & AUDIO_OUTPUT_FLAG_BIT_PERFECT) != AUDIO_OUTPUT_FLAG_NONE); + if (is_bit_perfect && (config->format == AUDIO_FORMAT_DEFAULT || + config->sample_rate == 0 || + config->channel_mask == AUDIO_CHANNEL_NONE)) { + ALOGE("%s request bit perfect playback, config(format=%#x, sample_rate=%u, " + "channel_mask=%#x) must be specified", __func__, config->format, + config->sample_rate, config->channel_mask); + return -EINVAL; + } + struct stream_out *out; out = (struct stream_out *)calloc(1, sizeof(struct stream_out)); @@ -980,9 +993,14 @@ static int adev_open_output_stream(struct audio_hw_device *hw_dev, } else if (profile_is_sample_rate_valid(&device_info->profile, config->sample_rate)) { proxy_config.rate = config->sample_rate; } else { + ret = -EINVAL; + if (is_bit_perfect) { + ALOGE("%s requesting bit-perfect but the sample rate(%u) is not valid", + __func__, config->sample_rate); + return ret; + } proxy_config.rate = config->sample_rate = profile_get_default_sample_rate(&device_info->profile); - ret = -EINVAL; } /* TODO: This is a problem if the input does not support this rate */ @@ -999,9 +1017,14 @@ static int adev_open_output_stream(struct audio_hw_device *hw_dev, if (profile_is_format_valid(&device_info->profile, fmt)) { proxy_config.format = fmt; } else { + ret = -EINVAL; + if (is_bit_perfect) { + ALOGE("%s request bit-perfect but the format(%#x) is not valid", + __func__, config->format); + return ret; + } proxy_config.format = profile_get_default_format(&device_info->profile); config->format = audio_format_from_pcm_format(proxy_config.format); - ret = -EINVAL; } } @@ -1039,7 +1062,17 @@ static int adev_open_output_stream(struct audio_hw_device *hw_dev, // and store THAT in proxy_config.channels proxy_config.channels = profile_get_closest_channel_count(&device_info->profile, out->hal_channel_count); - proxy_prepare(&device_info->proxy, &device_info->profile, &proxy_config); + if (is_bit_perfect && proxy_config.channels != out->hal_channel_count) { + ALOGE("%s request bit-perfect, but channel mask(%#x) cannot find exact match", + __func__, config->channel_mask); + return -EINVAL; + } + + ret = proxy_prepare(&device_info->proxy, &device_info->profile, &proxy_config, is_bit_perfect); + if (is_bit_perfect && ret != 0) { + ALOGE("%s failed to prepare proxy for bit-perfect playback, err=%d", __func__, ret); + return ret; + } out->config = proxy_config; list_add_tail(&out->alsa_devices, &device_info->list_node); @@ -1543,7 +1576,8 @@ static int adev_open_input_stream(struct audio_hw_device *hw_dev, // and store THAT in proxy_config.channels in->config.channels = profile_get_closest_channel_count(&device_info->profile, in->hal_channel_count); - ret = proxy_prepare(&device_info->proxy, &device_info->profile, &in->config); + ret = proxy_prepare(&device_info->proxy, &device_info->profile, &in->config, + false /*require_exact_match*/); if (ret == 0) { in->standby = true; @@ -1710,6 +1744,7 @@ static int adev_create_audio_patch(struct audio_hw_device *dev, struct pcm_config *config = NULL; struct stream_in *in = NULL; struct stream_out *out = NULL; + bool is_bit_perfect = false; unsigned int num_saved_devices = 0; int saved_cards[AUDIO_PATCH_PORTS_MAX]; @@ -1750,6 +1785,7 @@ static int adev_create_audio_patch(struct audio_hw_device *dev, alsa_devices = &out->alsa_devices; lock = &out->lock; config = &out->config; + is_bit_perfect = out->is_bit_perfect; } // Check if the patch handle match the recorded one if a valid patch handle is passed. @@ -1798,12 +1834,14 @@ static int adev_create_audio_patch(struct audio_hw_device *dev, struct alsa_device_info *device_info = stream_get_first_alsa_device(alsa_devices); if (device_info != NULL) saved_transferred_frames = device_info->proxy.transferred; - int ret = stream_set_new_devices(config, alsa_devices, num_configs, cards, devices, direction); + int ret = stream_set_new_devices( + config, alsa_devices, num_configs, cards, devices, direction, is_bit_perfect); if (ret != 0) { *handle = generatedPatchHandle ? AUDIO_PATCH_HANDLE_NONE : *handle; stream_set_new_devices( - config, alsa_devices, num_saved_devices, saved_cards, saved_devices, direction); + config, alsa_devices, num_saved_devices, saved_cards, saved_devices, direction, + is_bit_perfect); } else { *patch_handle = *handle; } From 4e7ab5d87798889a0db6b0f0b5084648fc468b7c Mon Sep 17 00:00:00 2001 From: Andy Hung Date: Mon, 27 Mar 2023 16:39:31 -0700 Subject: [PATCH 6/8] AudioParameter: Use for RemoteSubmix exiting Test: compiles Bug: 279106598 Change-Id: I50263a48584bac120c65123cd5bed09f60582089 --- modules/audio_remote_submix/audio_hw.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/audio_remote_submix/audio_hw.cpp b/modules/audio_remote_submix/audio_hw.cpp index f96854b5..5019ae5b 100644 --- a/modules/audio_remote_submix/audio_hw.cpp +++ b/modules/audio_remote_submix/audio_hw.cpp @@ -679,7 +679,8 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs) // FIXME this is using hard-coded strings but in the future, this functionality will be // converted to use audio HAL extensions required to support tunneling - if ((parms.getInt(String8("exiting"), exiting) == NO_ERROR) && (exiting > 0)) { + if ((parms.getInt(String8(AUDIO_PARAMETER_KEY_EXITING), exiting) == NO_ERROR) + && (exiting > 0)) { struct submix_audio_device * const rsxadev = audio_stream_get_submix_stream_out(stream)->dev; pthread_mutex_lock(&rsxadev->lock); From c8fbb82f0820e13ba8f22583c27c977a13b0b02b Mon Sep 17 00:00:00 2001 From: Mikhail Naganov Date: Fri, 28 Apr 2023 15:47:54 -0700 Subject: [PATCH 7/8] Add 'com.android.media' to apex_available of libhardware_headers Due to adding a dependency of libmedia_helper on libhardware_headers Bug: 278976019 Test: m Change-Id: I97df31b209630dc7fb6b46a0b0221c0d496e6375 --- Android.bp | 1 + 1 file changed, 1 insertion(+) diff --git a/Android.bp b/Android.bp index 88e0d44f..6baab685 100644 --- a/Android.bp +++ b/Android.bp @@ -64,6 +64,7 @@ cc_library_headers { apex_available: [ "//apex_available:platform", "com.android.btservices", + "com.android.media", "com.android.media.swcodec", ], min_sdk_version: "29", From 5b5e0c4552e71ba522b429d5a9e8756b7e72db60 Mon Sep 17 00:00:00 2001 From: jiabin Date: Tue, 16 May 2023 23:20:17 +0000 Subject: [PATCH 8/8] Use requested sample rate when it matches device sample rate. For input stream, the sample rate should be set as requested one if it matches the device sample rate and is valid. Bug: 282816698 Test: TH (cherry picked from https://android-review.googlesource.com/q/commit:abf24d3cc770f04b7ece1986fd51ce5db742a811) Merged-In: Iebee2b269062609ff7bcd460f48714ca64980e68 Change-Id: Iebee2b269062609ff7bcd460f48714ca64980e68 --- modules/usbaudio/audio_hal.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/usbaudio/audio_hal.c b/modules/usbaudio/audio_hal.c index 43f8d240..d77f7ec6 100644 --- a/modules/usbaudio/audio_hal.c +++ b/modules/usbaudio/audio_hal.c @@ -1510,6 +1510,8 @@ static int adev_open_input_stream(struct audio_hw_device *hw_dev, ret = 0; } } + } else if (profile_is_sample_rate_valid(&device_info->profile, config->sample_rate)) { + in->config.rate = config->sample_rate; } } else if (profile_is_sample_rate_valid(&device_info->profile, config->sample_rate)) { in->config.rate = config->sample_rate;