Loading hal/Android.mk +4 −0 Original line number Diff line number Diff line Loading @@ -183,6 +183,10 @@ ifeq ($(strip $(AUDIO_FEATURE_ENABLED_SND_MONITOR)), true) LOCAL_SRC_FILES += audio_extn/sndmonitor.c endif ifeq ($(strip $(AUDIO_FEATURE_ENABLED_USB_SERVICE_INTERVAL)), true) LOCAL_CFLAGS += -DUSB_SERVICE_INTERVAL_ENABLED endif LOCAL_SHARED_LIBRARIES += libbase libhidlbase libhwbinder libutils android.hardware.power@1.2 liblog LOCAL_SRC_FILES += audio_perf.cpp Loading hal/audio_extn/audio_extn.h +8 −0 Original line number Diff line number Diff line Loading @@ -81,6 +81,8 @@ int audio_extn_hfp_set_mic_mute(struct audio_device *adev, bool state); #define audio_extn_usb_get_max_bit_width(dir) (0) #define audio_extn_usb_sup_sample_rates(t, s, l) ((t), (s), (l), 0) /* fix unused warn */ #define audio_extn_usb_alive(adev) (false) #define audio_extn_usb_find_service_interval(m, p) ((m), (p), 0) /* fix unused warn */ #define audio_extn_usb_altset_for_service_interval(p, si, bw, sr, ch) (-1) #else void audio_extn_usb_init(void *adev); void audio_extn_usb_deinit(); Loading @@ -98,6 +100,12 @@ int audio_extn_usb_get_max_channels(bool is_playback); int audio_extn_usb_get_max_bit_width(bool is_playback); int audio_extn_usb_sup_sample_rates(bool is_playback, uint32_t *sr, uint32_t l); bool audio_extn_usb_alive(int card); unsigned long audio_extn_usb_find_service_interval(bool min, bool playback); int audio_extn_usb_altset_for_service_interval(bool is_playback, unsigned long service_interval, uint32_t *bit_width, uint32_t *sample_rate, uint32_t *channel_count); #endif Loading hal/audio_extn/usb.c +147 −6 Original line number Diff line number Diff line Loading @@ -37,10 +37,13 @@ #define CHANNEL_NUMBER_STR "Channels: " #define PLAYBACK_PROFILE_STR "Playback:" #define CAPTURE_PROFILE_STR "Capture:" #define DATA_PACKET_INTERVAL_STR "Data packet interval: " #define USB_SIDETONE_GAIN_STR "usb_sidetone_gain" #define ABS_SUB(A, B) (((A) > (B)) ? ((A) - (B)):((B) - (A))) #define SAMPLE_RATE_8000 8000 #define SAMPLE_RATE_11025 11025 #define DEFAULT_SERVICE_INTERVAL_US 1000 /* TODO: dynamically populate supported sample rates */ static uint32_t supported_sample_rates[] = {192000, 176400, 96000, 88200, 64000, 48000, 44100}; Loading @@ -50,10 +53,10 @@ static const uint32_t MAX_SAMPLE_RATE_SIZE = // assert on sizeof bm v/s size of rates if needed enum usb_usecase_type{ typedef enum usb_usecase_type{ USB_PLAYBACK = 0, USB_CAPTURE, }; } usb_usecase_type_t; enum { USB_SIDETONE_ENABLE_INDEX = 0, Loading @@ -67,6 +70,8 @@ struct usb_device_config { unsigned int channel_count; unsigned int rate_size; unsigned int rates[MAX_SAMPLE_RATE_SIZE]; unsigned long service_interval_us; usb_usecase_type_t type; }; struct usb_card_config { Loading Loading @@ -271,6 +276,43 @@ static int usb_get_sample_rates(int type, char *rates_str, return 0; } static int usb_get_service_interval(const char *interval_str_start, struct usb_device_config *usb_device_info) { unsigned long interval = 0; char time_unit[8] = {0}; int multiplier = 0; char *eol = strchr(interval_str_start, '\n'); if (!eol) { ALOGE("%s: No EOL found", __func__); return -1; } char *tmp = (char *)calloc(1, eol-interval_str_start+1); if (!tmp) { ALOGE("%s: failed to allocate tmp", __func__); return -1; } memcpy(tmp, interval_str_start, eol-interval_str_start); sscanf(tmp, "%lu %2s", &interval, &time_unit[0]); if (!strcmp(time_unit, "us")) { multiplier = 1; } else if (!strcmp(time_unit, "ms")) { multiplier = 1000; } else if (!strcmp(time_unit, "s")) { multiplier = 1000000; } else { ALOGE("%s: unknown time_unit %s, assume default", __func__, time_unit); interval = DEFAULT_SERVICE_INTERVAL_US; multiplier = 1; } interval *= multiplier; ALOGV("%s: set service_interval_us %lu", __func__, interval); usb_device_info->service_interval_us = interval; free(tmp); return 0; } static int usb_get_capability(int type, struct usb_card_config *usb_card_info, int card) Loading @@ -286,6 +328,7 @@ static int usb_get_capability(int type, char *target = NULL; char *read_buf = NULL; char *rates_str = NULL; char *interval_str_start = NULL; char path[128]; int ret = 0; char *bit_width_str = NULL; Loading Loading @@ -366,6 +409,7 @@ static int usb_get_capability(int type, ret = -ENOMEM; break; } usb_device_info->type = type; /* Bit bit_width parsing */ bit_width_start = strstr(str_start, "Format: "); if (bit_width_start == NULL) { Loading Loading @@ -443,6 +487,18 @@ static int usb_get_capability(int type, free(usb_device_info); continue; } // Data packet interval is an optional field. // Assume 1ms interval if this cannot be read usb_device_info->service_interval_us = DEFAULT_SERVICE_INTERVAL_US; interval_str_start = strstr(str_start, DATA_PACKET_INTERVAL_STR); if (interval_str_start != NULL) { interval_str_start += strlen(DATA_PACKET_INTERVAL_STR); ret = usb_get_service_interval(interval_str_start, usb_device_info); if (ret < 0) { ALOGE("%s: error unable to get service interval, assume default", __func__); } } /* Add to list if every field is valid */ list_add_tail(&usb_card_info->usb_device_conf_list, &usb_device_info->list); Loading Loading @@ -702,7 +758,9 @@ static bool usb_get_best_match_for_sample_rate( unsigned int bit_width, unsigned int channel_count, unsigned int stream_sample_rate, unsigned int *sr) unsigned int *sr, unsigned int service_interval, bool do_service_interval_check) { struct listnode *node_i; struct usb_device_config *dev_info; Loading @@ -720,7 +778,10 @@ static bool usb_get_best_match_for_sample_rate( "%s: USB ch(%d)bw(%d), stm ch(%d)bw(%d)sr(%d), candidate(%d)", __func__, dev_info->channel_count, dev_info->bit_width, channel_count, bit_width, stream_sample_rate, candidate); if ((dev_info->bit_width != bit_width) || dev_info->channel_count != channel_count) if ((dev_info->bit_width != bit_width) || (dev_info->channel_count != channel_count) || (do_service_interval_check && (dev_info->service_interval_us != service_interval))) continue; candidate = 0; Loading Loading @@ -787,7 +848,9 @@ static bool usb_audio_backend_apply_policy(struct listnode *dev_list, *bit_width, *channel_count, *sample_rate, sample_rate); sample_rate, 0 /*service int*/, false /*do service int check*/); exit: ALOGV("%s: Updated sample rate per profile: bit-width(%d) rate(%d) chs(%d)", __func__, *bit_width, *sample_rate, *channel_count); Loading Loading @@ -1110,6 +1173,84 @@ bool audio_extn_usb_alive(int card) { return access(path, F_OK) == 0; } unsigned long audio_extn_usb_find_service_interval(bool min, bool playback) { struct usb_card_config *card_info; struct usb_device_config *dev_info; struct listnode *node_i; struct listnode *node_j; unsigned long interval_us = min ? ULONG_MAX : 1; // 0 is invalid list_for_each(node_i, &usbmod->usb_card_conf_list) { card_info = node_to_item(node_i, struct usb_card_config, list); list_for_each(node_j, &card_info->usb_device_conf_list) { dev_info = node_to_item(node_j, struct usb_device_config, list); if ((playback && (dev_info->type == USB_PLAYBACK)) || (!playback && (dev_info->type == USB_CAPTURE))) { interval_us = min ? _MIN(interval_us, dev_info->service_interval_us) : _MAX(interval_us, dev_info->service_interval_us); } } break; } return interval_us; } int audio_extn_usb_altset_for_service_interval(bool playback, unsigned long service_interval, uint32_t *bit_width, uint32_t *sample_rate, uint32_t *channel_count) { struct usb_card_config *card_info; struct usb_device_config *dev_info; struct listnode *node_i; struct listnode *node_j; uint32_t bw = 0; uint32_t ch = 0; uint32_t sr = 0; list_for_each(node_i, &usbmod->usb_card_conf_list) { /* Currently only apply the first playback sound card configuration */ card_info = node_to_item(node_i, struct usb_card_config, list); list_for_each(node_j, &card_info->usb_device_conf_list) { dev_info = node_to_item(node_j, struct usb_device_config, list); if ((playback && dev_info->type == USB_PLAYBACK) || (!playback && dev_info->type == USB_CAPTURE)) { if (dev_info->service_interval_us != service_interval) continue; if (dev_info->bit_width > bw) { bw = dev_info->bit_width; ch = dev_info->channel_count; } else if (dev_info->bit_width == bw && dev_info->channel_count > ch) { ch = dev_info->channel_count; } } } break; } if (bw == 0 || ch == 0) return -1; list_for_each(node_i, &usbmod->usb_card_conf_list) { /* Currently only apply the first playback sound card configuration */ card_info = node_to_item(node_i, struct usb_card_config, list); if ((playback && usb_output_device(card_info->usb_device_type)) || (!playback && usb_input_device(card_info->usb_device_type))) { usb_get_best_match_for_sample_rate(&card_info->usb_device_conf_list, bw, ch, sr, &sr, service_interval, true); } break; } if (sr == 0) return -1; *bit_width = bw; *sample_rate = sr; *channel_count = ch; return 0; } void audio_extn_usb_init(void *adev) { if (usbmod == NULL) { Loading hal/audio_hw.c +62 −1 Original line number Diff line number Diff line Loading @@ -1869,6 +1869,54 @@ static int check_and_set_hdmi_channels(struct audio_device *adev, return 0; } static int check_and_set_usb_service_interval(struct audio_device *adev, struct audio_usecase *uc_info, bool min) { struct listnode *node; struct audio_usecase *usecase; bool switch_usecases = false; bool reconfig = false; if ((uc_info->id != USECASE_AUDIO_PLAYBACK_MMAP) && (uc_info->id != USECASE_AUDIO_PLAYBACK_ULL)) return -1; /* set if the valid usecase do not already exist */ list_for_each(node, &adev->usecase_list) { usecase = node_to_item(node, struct audio_usecase, list); if (usecase->type == PCM_PLAYBACK && (audio_is_usb_out_device(usecase->devices & AUDIO_DEVICE_OUT_ALL_USB))) { switch (usecase->id) { case USECASE_AUDIO_PLAYBACK_MMAP: case USECASE_AUDIO_PLAYBACK_ULL: // cannot reconfig while mmap/ull is present. return -1; default: switch_usecases = true; break; } } if (switch_usecases) break; } /* * client can try to set service interval in start_output_stream * to min or to 0 (i.e reset) in stop_output_stream . */ unsigned long service_interval = audio_extn_usb_find_service_interval(min, true /*playback*/); int ret = platform_set_usb_service_interval(adev->platform, true /*playback*/, service_interval, &reconfig); /* no change or not supported or no active usecases */ if (ret || !reconfig || !switch_usecases) return -1; return 0; #undef VALID_USECASE } static int stop_output_stream(struct stream_out *out) { int i, ret = 0; Loading Loading @@ -1901,7 +1949,6 @@ static int stop_output_stream(struct stream_out *out) disable_snd_device(adev, uc_info->out_snd_device); list_remove(&uc_info->list); free(uc_info); audio_extn_extspk_update(adev->extspk); Loading @@ -1916,8 +1963,17 @@ static int stop_output_stream(struct stream_out *out) if (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER) select_devices(adev, usecase->id); } } else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) { ret = check_and_set_usb_service_interval(adev, uc_info, false /*min*/); if (ret == 0) { /* default service interval was successfully updated, reopen USB backend with new service interval */ check_and_route_playback_usecases(adev, uc_info, uc_info->out_snd_device); } ret = 0; } free(uc_info); ALOGV("%s: exit: status(%d)", __func__, ret); return ret; } Loading Loading @@ -1971,6 +2027,11 @@ int start_output_stream(struct stream_out *out) /* This must be called before adding this usecase to the list */ if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) check_and_set_hdmi_channels(adev, out->config.channels); else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) { check_and_set_usb_service_interval(adev, uc_info, true /*min*/); /* USB backend is not reopened immediately. This is eventually done as part of select_devices */ } list_add_tail(&adev->usecase_list, &uc_info->list); Loading hal/msm8916/platform.c +16 −0 Original line number Diff line number Diff line Loading @@ -2512,3 +2512,19 @@ int platform_get_active_microphones(void *platform __unused, size_t *mic_count __unused) { return -ENOSYS; } int platform_set_usb_service_interval(void *platform __unused, bool playback __unused, unsigned long service_interval __unused, bool *reconfig) { *reconfig = false; return 0; } int platform_set_backend_cfg(const struct audio_device* adev, snd_device_t snd_device, const struct audio_backend_cfg *backend_cfg) { return -1; } Loading
hal/Android.mk +4 −0 Original line number Diff line number Diff line Loading @@ -183,6 +183,10 @@ ifeq ($(strip $(AUDIO_FEATURE_ENABLED_SND_MONITOR)), true) LOCAL_SRC_FILES += audio_extn/sndmonitor.c endif ifeq ($(strip $(AUDIO_FEATURE_ENABLED_USB_SERVICE_INTERVAL)), true) LOCAL_CFLAGS += -DUSB_SERVICE_INTERVAL_ENABLED endif LOCAL_SHARED_LIBRARIES += libbase libhidlbase libhwbinder libutils android.hardware.power@1.2 liblog LOCAL_SRC_FILES += audio_perf.cpp Loading
hal/audio_extn/audio_extn.h +8 −0 Original line number Diff line number Diff line Loading @@ -81,6 +81,8 @@ int audio_extn_hfp_set_mic_mute(struct audio_device *adev, bool state); #define audio_extn_usb_get_max_bit_width(dir) (0) #define audio_extn_usb_sup_sample_rates(t, s, l) ((t), (s), (l), 0) /* fix unused warn */ #define audio_extn_usb_alive(adev) (false) #define audio_extn_usb_find_service_interval(m, p) ((m), (p), 0) /* fix unused warn */ #define audio_extn_usb_altset_for_service_interval(p, si, bw, sr, ch) (-1) #else void audio_extn_usb_init(void *adev); void audio_extn_usb_deinit(); Loading @@ -98,6 +100,12 @@ int audio_extn_usb_get_max_channels(bool is_playback); int audio_extn_usb_get_max_bit_width(bool is_playback); int audio_extn_usb_sup_sample_rates(bool is_playback, uint32_t *sr, uint32_t l); bool audio_extn_usb_alive(int card); unsigned long audio_extn_usb_find_service_interval(bool min, bool playback); int audio_extn_usb_altset_for_service_interval(bool is_playback, unsigned long service_interval, uint32_t *bit_width, uint32_t *sample_rate, uint32_t *channel_count); #endif Loading
hal/audio_extn/usb.c +147 −6 Original line number Diff line number Diff line Loading @@ -37,10 +37,13 @@ #define CHANNEL_NUMBER_STR "Channels: " #define PLAYBACK_PROFILE_STR "Playback:" #define CAPTURE_PROFILE_STR "Capture:" #define DATA_PACKET_INTERVAL_STR "Data packet interval: " #define USB_SIDETONE_GAIN_STR "usb_sidetone_gain" #define ABS_SUB(A, B) (((A) > (B)) ? ((A) - (B)):((B) - (A))) #define SAMPLE_RATE_8000 8000 #define SAMPLE_RATE_11025 11025 #define DEFAULT_SERVICE_INTERVAL_US 1000 /* TODO: dynamically populate supported sample rates */ static uint32_t supported_sample_rates[] = {192000, 176400, 96000, 88200, 64000, 48000, 44100}; Loading @@ -50,10 +53,10 @@ static const uint32_t MAX_SAMPLE_RATE_SIZE = // assert on sizeof bm v/s size of rates if needed enum usb_usecase_type{ typedef enum usb_usecase_type{ USB_PLAYBACK = 0, USB_CAPTURE, }; } usb_usecase_type_t; enum { USB_SIDETONE_ENABLE_INDEX = 0, Loading @@ -67,6 +70,8 @@ struct usb_device_config { unsigned int channel_count; unsigned int rate_size; unsigned int rates[MAX_SAMPLE_RATE_SIZE]; unsigned long service_interval_us; usb_usecase_type_t type; }; struct usb_card_config { Loading Loading @@ -271,6 +276,43 @@ static int usb_get_sample_rates(int type, char *rates_str, return 0; } static int usb_get_service_interval(const char *interval_str_start, struct usb_device_config *usb_device_info) { unsigned long interval = 0; char time_unit[8] = {0}; int multiplier = 0; char *eol = strchr(interval_str_start, '\n'); if (!eol) { ALOGE("%s: No EOL found", __func__); return -1; } char *tmp = (char *)calloc(1, eol-interval_str_start+1); if (!tmp) { ALOGE("%s: failed to allocate tmp", __func__); return -1; } memcpy(tmp, interval_str_start, eol-interval_str_start); sscanf(tmp, "%lu %2s", &interval, &time_unit[0]); if (!strcmp(time_unit, "us")) { multiplier = 1; } else if (!strcmp(time_unit, "ms")) { multiplier = 1000; } else if (!strcmp(time_unit, "s")) { multiplier = 1000000; } else { ALOGE("%s: unknown time_unit %s, assume default", __func__, time_unit); interval = DEFAULT_SERVICE_INTERVAL_US; multiplier = 1; } interval *= multiplier; ALOGV("%s: set service_interval_us %lu", __func__, interval); usb_device_info->service_interval_us = interval; free(tmp); return 0; } static int usb_get_capability(int type, struct usb_card_config *usb_card_info, int card) Loading @@ -286,6 +328,7 @@ static int usb_get_capability(int type, char *target = NULL; char *read_buf = NULL; char *rates_str = NULL; char *interval_str_start = NULL; char path[128]; int ret = 0; char *bit_width_str = NULL; Loading Loading @@ -366,6 +409,7 @@ static int usb_get_capability(int type, ret = -ENOMEM; break; } usb_device_info->type = type; /* Bit bit_width parsing */ bit_width_start = strstr(str_start, "Format: "); if (bit_width_start == NULL) { Loading Loading @@ -443,6 +487,18 @@ static int usb_get_capability(int type, free(usb_device_info); continue; } // Data packet interval is an optional field. // Assume 1ms interval if this cannot be read usb_device_info->service_interval_us = DEFAULT_SERVICE_INTERVAL_US; interval_str_start = strstr(str_start, DATA_PACKET_INTERVAL_STR); if (interval_str_start != NULL) { interval_str_start += strlen(DATA_PACKET_INTERVAL_STR); ret = usb_get_service_interval(interval_str_start, usb_device_info); if (ret < 0) { ALOGE("%s: error unable to get service interval, assume default", __func__); } } /* Add to list if every field is valid */ list_add_tail(&usb_card_info->usb_device_conf_list, &usb_device_info->list); Loading Loading @@ -702,7 +758,9 @@ static bool usb_get_best_match_for_sample_rate( unsigned int bit_width, unsigned int channel_count, unsigned int stream_sample_rate, unsigned int *sr) unsigned int *sr, unsigned int service_interval, bool do_service_interval_check) { struct listnode *node_i; struct usb_device_config *dev_info; Loading @@ -720,7 +778,10 @@ static bool usb_get_best_match_for_sample_rate( "%s: USB ch(%d)bw(%d), stm ch(%d)bw(%d)sr(%d), candidate(%d)", __func__, dev_info->channel_count, dev_info->bit_width, channel_count, bit_width, stream_sample_rate, candidate); if ((dev_info->bit_width != bit_width) || dev_info->channel_count != channel_count) if ((dev_info->bit_width != bit_width) || (dev_info->channel_count != channel_count) || (do_service_interval_check && (dev_info->service_interval_us != service_interval))) continue; candidate = 0; Loading Loading @@ -787,7 +848,9 @@ static bool usb_audio_backend_apply_policy(struct listnode *dev_list, *bit_width, *channel_count, *sample_rate, sample_rate); sample_rate, 0 /*service int*/, false /*do service int check*/); exit: ALOGV("%s: Updated sample rate per profile: bit-width(%d) rate(%d) chs(%d)", __func__, *bit_width, *sample_rate, *channel_count); Loading Loading @@ -1110,6 +1173,84 @@ bool audio_extn_usb_alive(int card) { return access(path, F_OK) == 0; } unsigned long audio_extn_usb_find_service_interval(bool min, bool playback) { struct usb_card_config *card_info; struct usb_device_config *dev_info; struct listnode *node_i; struct listnode *node_j; unsigned long interval_us = min ? ULONG_MAX : 1; // 0 is invalid list_for_each(node_i, &usbmod->usb_card_conf_list) { card_info = node_to_item(node_i, struct usb_card_config, list); list_for_each(node_j, &card_info->usb_device_conf_list) { dev_info = node_to_item(node_j, struct usb_device_config, list); if ((playback && (dev_info->type == USB_PLAYBACK)) || (!playback && (dev_info->type == USB_CAPTURE))) { interval_us = min ? _MIN(interval_us, dev_info->service_interval_us) : _MAX(interval_us, dev_info->service_interval_us); } } break; } return interval_us; } int audio_extn_usb_altset_for_service_interval(bool playback, unsigned long service_interval, uint32_t *bit_width, uint32_t *sample_rate, uint32_t *channel_count) { struct usb_card_config *card_info; struct usb_device_config *dev_info; struct listnode *node_i; struct listnode *node_j; uint32_t bw = 0; uint32_t ch = 0; uint32_t sr = 0; list_for_each(node_i, &usbmod->usb_card_conf_list) { /* Currently only apply the first playback sound card configuration */ card_info = node_to_item(node_i, struct usb_card_config, list); list_for_each(node_j, &card_info->usb_device_conf_list) { dev_info = node_to_item(node_j, struct usb_device_config, list); if ((playback && dev_info->type == USB_PLAYBACK) || (!playback && dev_info->type == USB_CAPTURE)) { if (dev_info->service_interval_us != service_interval) continue; if (dev_info->bit_width > bw) { bw = dev_info->bit_width; ch = dev_info->channel_count; } else if (dev_info->bit_width == bw && dev_info->channel_count > ch) { ch = dev_info->channel_count; } } } break; } if (bw == 0 || ch == 0) return -1; list_for_each(node_i, &usbmod->usb_card_conf_list) { /* Currently only apply the first playback sound card configuration */ card_info = node_to_item(node_i, struct usb_card_config, list); if ((playback && usb_output_device(card_info->usb_device_type)) || (!playback && usb_input_device(card_info->usb_device_type))) { usb_get_best_match_for_sample_rate(&card_info->usb_device_conf_list, bw, ch, sr, &sr, service_interval, true); } break; } if (sr == 0) return -1; *bit_width = bw; *sample_rate = sr; *channel_count = ch; return 0; } void audio_extn_usb_init(void *adev) { if (usbmod == NULL) { Loading
hal/audio_hw.c +62 −1 Original line number Diff line number Diff line Loading @@ -1869,6 +1869,54 @@ static int check_and_set_hdmi_channels(struct audio_device *adev, return 0; } static int check_and_set_usb_service_interval(struct audio_device *adev, struct audio_usecase *uc_info, bool min) { struct listnode *node; struct audio_usecase *usecase; bool switch_usecases = false; bool reconfig = false; if ((uc_info->id != USECASE_AUDIO_PLAYBACK_MMAP) && (uc_info->id != USECASE_AUDIO_PLAYBACK_ULL)) return -1; /* set if the valid usecase do not already exist */ list_for_each(node, &adev->usecase_list) { usecase = node_to_item(node, struct audio_usecase, list); if (usecase->type == PCM_PLAYBACK && (audio_is_usb_out_device(usecase->devices & AUDIO_DEVICE_OUT_ALL_USB))) { switch (usecase->id) { case USECASE_AUDIO_PLAYBACK_MMAP: case USECASE_AUDIO_PLAYBACK_ULL: // cannot reconfig while mmap/ull is present. return -1; default: switch_usecases = true; break; } } if (switch_usecases) break; } /* * client can try to set service interval in start_output_stream * to min or to 0 (i.e reset) in stop_output_stream . */ unsigned long service_interval = audio_extn_usb_find_service_interval(min, true /*playback*/); int ret = platform_set_usb_service_interval(adev->platform, true /*playback*/, service_interval, &reconfig); /* no change or not supported or no active usecases */ if (ret || !reconfig || !switch_usecases) return -1; return 0; #undef VALID_USECASE } static int stop_output_stream(struct stream_out *out) { int i, ret = 0; Loading Loading @@ -1901,7 +1949,6 @@ static int stop_output_stream(struct stream_out *out) disable_snd_device(adev, uc_info->out_snd_device); list_remove(&uc_info->list); free(uc_info); audio_extn_extspk_update(adev->extspk); Loading @@ -1916,8 +1963,17 @@ static int stop_output_stream(struct stream_out *out) if (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER) select_devices(adev, usecase->id); } } else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) { ret = check_and_set_usb_service_interval(adev, uc_info, false /*min*/); if (ret == 0) { /* default service interval was successfully updated, reopen USB backend with new service interval */ check_and_route_playback_usecases(adev, uc_info, uc_info->out_snd_device); } ret = 0; } free(uc_info); ALOGV("%s: exit: status(%d)", __func__, ret); return ret; } Loading Loading @@ -1971,6 +2027,11 @@ int start_output_stream(struct stream_out *out) /* This must be called before adding this usecase to the list */ if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) check_and_set_hdmi_channels(adev, out->config.channels); else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) { check_and_set_usb_service_interval(adev, uc_info, true /*min*/); /* USB backend is not reopened immediately. This is eventually done as part of select_devices */ } list_add_tail(&adev->usecase_list, &uc_info->list); Loading
hal/msm8916/platform.c +16 −0 Original line number Diff line number Diff line Loading @@ -2512,3 +2512,19 @@ int platform_get_active_microphones(void *platform __unused, size_t *mic_count __unused) { return -ENOSYS; } int platform_set_usb_service_interval(void *platform __unused, bool playback __unused, unsigned long service_interval __unused, bool *reconfig) { *reconfig = false; return 0; } int platform_set_backend_cfg(const struct audio_device* adev, snd_device_t snd_device, const struct audio_backend_cfg *backend_cfg) { return -1; }