blob: 14ef9939e84475ba4e857fd9c3e8fc42f3dd8b7a [file] [log] [blame]
Simon Wilson19957a32012-04-06 16:17:12 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Paul McLean9ab869a2015-01-13 09:37:06 -080017#define LOG_TAG "modules.usbaudio.audio_hal"
Paul McLeancf5310a2018-08-22 14:33:12 -070018/* #define LOG_NDEBUG 0 */
Simon Wilson19957a32012-04-06 16:17:12 -070019
20#include <errno.h>
Mark Salyzyn88e458a2014-04-28 12:30:44 -070021#include <inttypes.h>
Simon Wilson19957a32012-04-06 16:17:12 -070022#include <pthread.h>
23#include <stdint.h>
Simon Wilson19957a32012-04-06 16:17:12 -070024#include <stdlib.h>
Mark Salyzyn88e458a2014-04-28 12:30:44 -070025#include <sys/time.h>
Tri Vo00a86732017-06-27 11:33:36 -070026#include <unistd.h>
Simon Wilson19957a32012-04-06 16:17:12 -070027
Mark Salyzyn88e458a2014-04-28 12:30:44 -070028#include <log/log.h>
Paul McLean6a75e4e2016-05-25 14:09:02 -060029#include <cutils/list.h>
Simon Wilson19957a32012-04-06 16:17:12 -070030#include <cutils/str_parms.h>
31#include <cutils/properties.h>
32
Simon Wilson19957a32012-04-06 16:17:12 -070033#include <hardware/audio.h>
Paul McLeane32cbc12014-06-25 10:42:07 -070034#include <hardware/audio_alsaops.h>
35#include <hardware/hardware.h>
36
37#include <system/audio.h>
Simon Wilson19957a32012-04-06 16:17:12 -070038
39#include <tinyalsa/asoundlib.h>
40
Paul McLeanc2201152014-07-16 13:46:07 -070041#include <audio_utils/channels.h>
42
Paul McLeanc88e6ae2014-07-16 09:48:34 -070043#include "alsa_device_profile.h"
44#include "alsa_device_proxy.h"
Paul McLean9ab869a2015-01-13 09:37:06 -080045#include "alsa_logging.h"
Paul McLeanf62d75e2014-07-11 15:14:19 -070046
Paul McLean1d585cc2016-05-24 11:28:10 -060047/* Lock play & record samples rates at or above this threshold */
48#define RATELOCK_THRESHOLD 96000
49
Paul McLeancfdbd6b2018-07-27 11:16:02 -060050#define max(a, b) ((a) > (b) ? (a) : (b))
51#define min(a, b) ((a) < (b) ? (a) : (b))
52
Simon Wilson19957a32012-04-06 16:17:12 -070053struct audio_device {
54 struct audio_hw_device hw_device;
55
56 pthread_mutex_t lock; /* see note below on mutex acquisition order */
Paul McLeaneedc92e2013-12-19 15:46:15 -080057
58 /* output */
Paul McLean6a75e4e2016-05-25 14:09:02 -060059 struct listnode output_stream_list;
Paul McLeaneedc92e2013-12-19 15:46:15 -080060
61 /* input */
Paul McLean6a75e4e2016-05-25 14:09:02 -060062 struct listnode input_stream_list;
Paul McLeaneedc92e2013-12-19 15:46:15 -080063
Paul McLean1d585cc2016-05-24 11:28:10 -060064 /* lock input & output sample rates */
65 /*FIXME - How do we address multiple output streams? */
Paul McLeancfdbd6b2018-07-27 11:16:02 -060066 uint32_t device_sample_rate; // this should be a rate that is common to both input & output
Paul McLean1d585cc2016-05-24 11:28:10 -060067
Eric Laurent253def92014-09-14 12:18:18 -070068 bool mic_muted;
69
Andy Hungb10ce6d2017-10-27 19:37:58 -070070 int32_t inputs_open; /* number of input streams currently open. */
Simon Wilson19957a32012-04-06 16:17:12 -070071};
72
Paul McLean994ac072016-06-02 15:33:24 -060073struct stream_lock {
74 pthread_mutex_t lock; /* see note below on mutex acquisition order */
75 pthread_mutex_t pre_lock; /* acquire before lock to avoid DOS by playback thread */
76};
77
jiabin8b265c92020-10-21 15:16:40 -070078struct alsa_device_info {
79 alsa_device_profile profile; /* The profile of the ALSA device */
80 alsa_device_proxy proxy; /* The state */
81 struct listnode list_node;
82};
83
Simon Wilson19957a32012-04-06 16:17:12 -070084struct stream_out {
85 struct audio_stream_out stream;
86
Paul McLeancf5310a2018-08-22 14:33:12 -070087 struct stream_lock lock;
Paul McLean994ac072016-06-02 15:33:24 -060088
Paul McLeaneedc92e2013-12-19 15:46:15 -080089 bool standby;
90
Paul McLean76dba682016-06-01 12:29:11 -060091 struct audio_device *adev; /* hardware information - only using this for the lock */
Paul McLeanc88e6ae2014-07-16 09:48:34 -070092
jiabin8b265c92020-10-21 15:16:40 -070093 struct listnode alsa_devices; /* The ALSA devices connected to the stream. */
Paul McLeaneedc92e2013-12-19 15:46:15 -080094
Andy Hung03576be2014-07-21 21:16:45 -070095 unsigned hal_channel_count; /* channel count exposed to AudioFlinger.
96 * This may differ from the device channel count when
97 * the device is not compatible with AudioFlinger
98 * capabilities, e.g. exposes too many channels or
99 * too few channels. */
Paul McLean64345f82016-06-06 13:26:05 -0600100 audio_channel_mask_t hal_channel_mask; /* USB devices deal in channel counts, not masks
101 * so the proxy doesn't have a channel_mask, but
102 * audio HALs need to talk about channel masks
103 * so expose the one calculated by
104 * adev_open_output_stream */
Andy Hung182ddc72015-05-05 23:37:30 -0700105
Paul McLean6a75e4e2016-05-25 14:09:02 -0600106 struct listnode list_node;
107
Paul McLeaneedc92e2013-12-19 15:46:15 -0800108 void * conversion_buffer; /* any conversions are put into here
109 * they could come from here too if
110 * there was a previous conversion */
111 size_t conversion_buffer_size; /* in bytes */
112};
113
Paul McLeaneedc92e2013-12-19 15:46:15 -0800114struct stream_in {
115 struct audio_stream_in stream;
116
Paul McLean994ac072016-06-02 15:33:24 -0600117 struct stream_lock lock;
118
Simon Wilson19957a32012-04-06 16:17:12 -0700119 bool standby;
120
Paul McLean76dba682016-06-01 12:29:11 -0600121 struct audio_device *adev; /* hardware information - only using this for the lock */
Paul McLeaneedc92e2013-12-19 15:46:15 -0800122
jiabin8b265c92020-10-21 15:16:40 -0700123 struct listnode alsa_devices; /* The ALSA devices connected to the stream. */
Paul McLeanf62d75e2014-07-11 15:14:19 -0700124
Paul McLean2cfd81b2014-09-15 12:32:23 -0700125 unsigned hal_channel_count; /* channel count exposed to AudioFlinger.
126 * This may differ from the device channel count when
127 * the device is not compatible with AudioFlinger
128 * capabilities, e.g. exposes too many channels or
129 * too few channels. */
Paul McLean64345f82016-06-06 13:26:05 -0600130 audio_channel_mask_t hal_channel_mask; /* USB devices deal in channel counts, not masks
131 * so the proxy doesn't have a channel_mask, but
132 * audio HALs need to talk about channel masks
133 * so expose the one calculated by
134 * adev_open_input_stream */
Andy Hung780f1f82015-04-22 22:14:39 -0700135
Paul McLean6a75e4e2016-05-25 14:09:02 -0600136 struct listnode list_node;
137
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700138 /* We may need to read more data from the device in order to data reduce to 16bit, 4chan */
Paul McLean30f41852014-04-16 15:44:20 -0700139 void * conversion_buffer; /* any conversions are put into here
140 * they could come from here too if
141 * there was a previous conversion */
142 size_t conversion_buffer_size; /* in bytes */
Simon Wilson19957a32012-04-06 16:17:12 -0700143};
144
Paul McLean994ac072016-06-02 15:33:24 -0600145/*
146 * Locking Helpers
147 */
Paul McLeaneedc92e2013-12-19 15:46:15 -0800148/*
Eric Laurent70318092015-06-19 17:49:17 -0700149 * NOTE: when multiple mutexes have to be acquired, always take the
150 * stream_in or stream_out mutex first, followed by the audio_device mutex.
151 * stream pre_lock is always acquired before stream lock to prevent starvation of control thread by
152 * higher priority playback or capture thread.
153 */
154
Paul McLean994ac072016-06-02 15:33:24 -0600155static void stream_lock_init(struct stream_lock *lock) {
156 pthread_mutex_init(&lock->lock, (const pthread_mutexattr_t *) NULL);
157 pthread_mutex_init(&lock->pre_lock, (const pthread_mutexattr_t *) NULL);
158}
159
160static void stream_lock(struct stream_lock *lock) {
161 pthread_mutex_lock(&lock->pre_lock);
162 pthread_mutex_lock(&lock->lock);
163 pthread_mutex_unlock(&lock->pre_lock);
164}
165
166static void stream_unlock(struct stream_lock *lock) {
167 pthread_mutex_unlock(&lock->lock);
168}
169
170static void device_lock(struct audio_device *adev) {
171 pthread_mutex_lock(&adev->lock);
172}
173
174static int device_try_lock(struct audio_device *adev) {
175 return pthread_mutex_trylock(&adev->lock);
176}
177
178static void device_unlock(struct audio_device *adev) {
179 pthread_mutex_unlock(&adev->lock);
180}
181
182/*
183 * streams list management
184 */
185static void adev_add_stream_to_list(
186 struct audio_device* adev, struct listnode* list, struct listnode* stream_node) {
187 device_lock(adev);
188
189 list_add_tail(list, stream_node);
190
191 device_unlock(adev);
192}
193
194static void adev_remove_stream_from_list(
195 struct audio_device* adev, struct listnode* stream_node) {
196 device_lock(adev);
197
198 list_remove(stream_node);
199
200 device_unlock(adev);
201}
202
Eric Laurent70318092015-06-19 17:49:17 -0700203/*
Paul McLean0f1753e2014-12-02 12:36:45 -0700204 * Extract the card and device numbers from the supplied key/value pairs.
205 * kvpairs A null-terminated string containing the key/value pairs or card and device.
206 * i.e. "card=1;device=42"
207 * card A pointer to a variable to receive the parsed-out card number.
208 * device A pointer to a variable to receive the parsed-out device number.
209 * NOTE: The variables pointed to by card and device return -1 (undefined) if the
210 * associated key/value pair is not found in the provided string.
Paul McLean65ec72b2015-02-18 09:13:24 -0800211 * Return true if the kvpairs string contain a card/device spec, false otherwise.
Paul McLean0f1753e2014-12-02 12:36:45 -0700212 */
Paul McLean65ec72b2015-02-18 09:13:24 -0800213static bool parse_card_device_params(const char *kvpairs, int *card, int *device)
Paul McLean0f1753e2014-12-02 12:36:45 -0700214{
215 struct str_parms * parms = str_parms_create_str(kvpairs);
216 char value[32];
217 int param_val;
218
219 // initialize to "undefined" state.
220 *card = -1;
221 *device = -1;
222
223 param_val = str_parms_get_str(parms, "card", value, sizeof(value));
224 if (param_val >= 0) {
225 *card = atoi(value);
226 }
227
228 param_val = str_parms_get_str(parms, "device", value, sizeof(value));
229 if (param_val >= 0) {
230 *device = atoi(value);
231 }
232
233 str_parms_destroy(parms);
Paul McLean65ec72b2015-02-18 09:13:24 -0800234
235 return *card >= 0 && *device >= 0;
Paul McLean0f1753e2014-12-02 12:36:45 -0700236}
237
Andy Hung4e6a1c02017-10-27 20:31:46 -0700238static char *device_get_parameters(const alsa_device_profile *profile, const char * keys)
Paul McLeaneedc92e2013-12-19 15:46:15 -0800239{
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700240 if (profile->card < 0 || profile->device < 0) {
241 return strdup("");
Paul McLeaneedc92e2013-12-19 15:46:15 -0800242 }
Paul McLeane32cbc12014-06-25 10:42:07 -0700243
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700244 struct str_parms *query = str_parms_create_str(keys);
245 struct str_parms *result = str_parms_create();
Paul McLeane32cbc12014-06-25 10:42:07 -0700246
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700247 /* These keys are from hardware/libhardware/include/audio.h */
248 /* supported sample rates */
249 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
250 char* rates_list = profile_get_sample_rate_strs(profile);
251 str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
252 rates_list);
253 free(rates_list);
Paul McLeane32cbc12014-06-25 10:42:07 -0700254 }
255
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700256 /* supported channel counts */
257 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
258 char* channels_list = profile_get_channel_count_strs(profile);
259 str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_CHANNELS,
260 channels_list);
261 free(channels_list);
Paul McLeane32cbc12014-06-25 10:42:07 -0700262 }
263
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700264 /* supported sample formats */
265 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
266 char * format_params = profile_get_format_strs(profile);
267 str_parms_add_str(result, AUDIO_PARAMETER_STREAM_SUP_FORMATS,
268 format_params);
269 free(format_params);
Paul McLeanf62d75e2014-07-11 15:14:19 -0700270 }
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700271 str_parms_destroy(query);
Paul McLeanf62d75e2014-07-11 15:14:19 -0700272
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700273 char* result_str = str_parms_to_str(result);
274 str_parms_destroy(result);
Paul McLeanf62d75e2014-07-11 15:14:19 -0700275
Paul McLean65ec72b2015-02-18 09:13:24 -0800276 ALOGV("device_get_parameters = %s", result_str);
Paul McLeanf62d75e2014-07-11 15:14:19 -0700277
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700278 return result_str;
Paul McLeaneedc92e2013-12-19 15:46:15 -0800279}
280
281/*
282 * HAl Functions
283 */
Simon Wilson19957a32012-04-06 16:17:12 -0700284/**
285 * NOTE: when multiple mutexes have to be acquired, always respect the
286 * following order: hw device > out stream
287 */
288
jiabin8b265c92020-10-21 15:16:40 -0700289static struct alsa_device_info* stream_get_first_alsa_device(const struct listnode *alsa_devices) {
290 if (list_empty(alsa_devices)) {
291 return NULL;
292 }
293 return node_to_item(list_head(alsa_devices), struct alsa_device_info, list_node);
294}
295
296static void stream_dump_alsa_devices(const struct listnode *alsa_devices, int fd) {
297 struct listnode *node;
298 size_t i = 0;
299 list_for_each(node, alsa_devices) {
300 struct alsa_device_info *device_info =
301 node_to_item(node, struct alsa_device_info, list_node);
302 dprintf(fd, "Output Profile %zu:\n", i);
303 profile_dump(&device_info->profile, fd);
304
305 dprintf(fd, "Output Proxy %zu:\n", i);
306 proxy_dump(&device_info->proxy, fd);
307 }
308}
309
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700310/*
311 * OUT functions
312 */
Simon Wilson19957a32012-04-06 16:17:12 -0700313static uint32_t out_get_sample_rate(const struct audio_stream *stream)
314{
jiabin8b265c92020-10-21 15:16:40 -0700315 struct alsa_device_info *device_info = stream_get_first_alsa_device(
316 &((struct stream_out*)stream)->alsa_devices);
317 if (device_info == NULL) {
318 ALOGW("%s device info is null", __func__);
319 return 0;
320 }
321 uint32_t rate = proxy_get_sample_rate(&device_info->proxy);
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700322 ALOGV("out_get_sample_rate() = %d", rate);
323 return rate;
Simon Wilson19957a32012-04-06 16:17:12 -0700324}
325
326static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
327{
328 return 0;
329}
330
331static size_t out_get_buffer_size(const struct audio_stream *stream)
332{
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700333 const struct stream_out* out = (const struct stream_out*)stream;
jiabin8b265c92020-10-21 15:16:40 -0700334 const struct alsa_device_info* device_info = stream_get_first_alsa_device(&out->alsa_devices);
335 if (device_info == NULL) {
336 ALOGW("%s device info is null", __func__);
337 return 0;
338 }
339 return proxy_get_period_size(&device_info->proxy) * audio_stream_out_frame_size(&(out->stream));
Simon Wilson19957a32012-04-06 16:17:12 -0700340}
341
342static uint32_t out_get_channels(const struct audio_stream *stream)
343{
Andy Hung03576be2014-07-21 21:16:45 -0700344 const struct stream_out *out = (const struct stream_out*)stream;
Andy Hung182ddc72015-05-05 23:37:30 -0700345 return out->hal_channel_mask;
Simon Wilson19957a32012-04-06 16:17:12 -0700346}
347
348static audio_format_t out_get_format(const struct audio_stream *stream)
349{
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700350 /* Note: The HAL doesn't do any FORMAT conversion at this time. It
351 * Relies on the framework to provide data in the specified format.
352 * This could change in the future.
353 */
jiabin8b265c92020-10-21 15:16:40 -0700354 struct alsa_device_info *device_info = stream_get_first_alsa_device(
355 &((struct stream_out*)stream)->alsa_devices);
356 if (device_info == NULL) {
357 ALOGW("%s device info is null", __func__);
358 return AUDIO_FORMAT_DEFAULT;
359 }
360 audio_format_t format = audio_format_from_pcm_format(proxy_get_format(&device_info->proxy));
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700361 return format;
Simon Wilson19957a32012-04-06 16:17:12 -0700362}
363
364static int out_set_format(struct audio_stream *stream, audio_format_t format)
365{
366 return 0;
367}
368
369static int out_standby(struct audio_stream *stream)
370{
371 struct stream_out *out = (struct stream_out *)stream;
372
Paul McLean994ac072016-06-02 15:33:24 -0600373 stream_lock(&out->lock);
Simon Wilson19957a32012-04-06 16:17:12 -0700374 if (!out->standby) {
jiabin8b265c92020-10-21 15:16:40 -0700375 struct listnode *node;
376 list_for_each(node, &out->alsa_devices) {
377 struct alsa_device_info *device_info =
378 node_to_item(node, struct alsa_device_info, list_node);
379 proxy_close(&device_info->proxy);
380 }
Simon Wilson19957a32012-04-06 16:17:12 -0700381 out->standby = true;
382 }
Paul McLean994ac072016-06-02 15:33:24 -0600383 stream_unlock(&out->lock);
Simon Wilson19957a32012-04-06 16:17:12 -0700384 return 0;
385}
386
Paul McLean6a75e4e2016-05-25 14:09:02 -0600387static int out_dump(const struct audio_stream *stream, int fd) {
388 const struct stream_out* out_stream = (const struct stream_out*) stream;
389
390 if (out_stream != NULL) {
jiabin8b265c92020-10-21 15:16:40 -0700391 stream_dump_alsa_devices(&out_stream->alsa_devices, fd);
Paul McLean6a75e4e2016-05-25 14:09:02 -0600392 }
393
Simon Wilson19957a32012-04-06 16:17:12 -0700394 return 0;
395}
396
397static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
398{
Paul McLean65ec72b2015-02-18 09:13:24 -0800399 ALOGV("out_set_parameters() keys:%s", kvpairs);
Paul McLeaneedc92e2013-12-19 15:46:15 -0800400
Simon Wilson19957a32012-04-06 16:17:12 -0700401 struct stream_out *out = (struct stream_out *)stream;
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700402
Paul McLeaneedc92e2013-12-19 15:46:15 -0800403 int ret_value = 0;
Eric Laurent05333d42014-08-04 20:29:17 -0700404 int card = -1;
405 int device = -1;
Simon Wilson19957a32012-04-06 16:17:12 -0700406
Paul McLean65ec72b2015-02-18 09:13:24 -0800407 if (!parse_card_device_params(kvpairs, &card, &device)) {
408 // nothing to do
409 return ret_value;
410 }
411
Paul McLean994ac072016-06-02 15:33:24 -0600412 stream_lock(&out->lock);
jiabin8b265c92020-10-21 15:16:40 -0700413 struct alsa_device_info* device_info = stream_get_first_alsa_device(&out->alsa_devices);
414 if (device_info != NULL && !profile_is_cached_for(&device_info->profile, card, device)) {
Eric Laurent05333d42014-08-04 20:29:17 -0700415 /* cannot read pcm device info if playback is active */
416 if (!out->standby)
417 ret_value = -ENOSYS;
418 else {
jiabin8b265c92020-10-21 15:16:40 -0700419 int saved_card = device_info->profile.card;
420 int saved_device = device_info->profile.device;
421 device_info->profile.card = card;
422 device_info->profile.device = device;
423 ret_value = profile_read_device_info(&device_info->profile) ? 0 : -EINVAL;
Eric Laurent05333d42014-08-04 20:29:17 -0700424 if (ret_value != 0) {
jiabin8b265c92020-10-21 15:16:40 -0700425 device_info->profile.card = saved_card;
426 device_info->profile.device = saved_device;
Eric Laurent05333d42014-08-04 20:29:17 -0700427 }
428 }
Paul McLeaneedc92e2013-12-19 15:46:15 -0800429 }
Paul McLean2c6196f2014-08-20 16:50:25 -0700430
Paul McLean994ac072016-06-02 15:33:24 -0600431 stream_unlock(&out->lock);
Simon Wilson19957a32012-04-06 16:17:12 -0700432
Paul McLeaneedc92e2013-12-19 15:46:15 -0800433 return ret_value;
Simon Wilson19957a32012-04-06 16:17:12 -0700434}
435
Paul McLeanf62d75e2014-07-11 15:14:19 -0700436static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
437{
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700438 struct stream_out *out = (struct stream_out *)stream;
Paul McLean994ac072016-06-02 15:33:24 -0600439 stream_lock(&out->lock);
jiabin8b265c92020-10-21 15:16:40 -0700440 struct alsa_device_info *device_info = stream_get_first_alsa_device(&out->alsa_devices);
441 char *params_str = NULL;
442 if (device_info != NULL) {
443 params_str = device_get_parameters(&device_info->profile, keys);
444 }
Paul McLean994ac072016-06-02 15:33:24 -0600445 stream_unlock(&out->lock);
Paul McLeanf62d75e2014-07-11 15:14:19 -0700446 return params_str;
447}
448
Simon Wilson19957a32012-04-06 16:17:12 -0700449static uint32_t out_get_latency(const struct audio_stream_out *stream)
450{
jiabin8b265c92020-10-21 15:16:40 -0700451 struct alsa_device_info *device_info = stream_get_first_alsa_device(
452 &((struct stream_out*)stream)->alsa_devices);
453 if (device_info == NULL) {
454 ALOGW("%s device info is null", __func__);
455 return 0;
456 }
457 return proxy_get_latency(&device_info->proxy);
Simon Wilson19957a32012-04-06 16:17:12 -0700458}
459
Paul McLean30f41852014-04-16 15:44:20 -0700460static int out_set_volume(struct audio_stream_out *stream, float left, float right)
Simon Wilson19957a32012-04-06 16:17:12 -0700461{
462 return -ENOSYS;
463}
464
Paul McLeaneedc92e2013-12-19 15:46:15 -0800465/* must be called with hw device and output stream mutexes locked */
466static int start_output_stream(struct stream_out *out)
467{
jiabin8b265c92020-10-21 15:16:40 -0700468 int status = 0;
469 struct listnode *node;
470 list_for_each(node, &out->alsa_devices) {
471 struct alsa_device_info *device_info =
472 node_to_item(node, struct alsa_device_info, list_node);
473 ALOGV("start_output_stream(card:%d device:%d)",
474 device_info->profile.card, device_info->profile.device);
475 status = proxy_open(&device_info->proxy);
476 if (status != 0) {
477 ALOGE("%s failed to open device(card: %d device: %d)",
478 __func__, device_info->profile.card, device_info->profile.device);
479 goto exit;
480 }
481 }
Paul McLeaneedc92e2013-12-19 15:46:15 -0800482
jiabin8b265c92020-10-21 15:16:40 -0700483exit:
484 if (status != 0) {
485 list_for_each(node, &out->alsa_devices) {
486 struct alsa_device_info *device_info =
487 node_to_item(node, struct alsa_device_info, list_node);
488 proxy_close(&device_info->proxy);
489 }
490
491 }
492 return status;
Paul McLeaneedc92e2013-12-19 15:46:15 -0800493}
494
495static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, size_t bytes)
Simon Wilson19957a32012-04-06 16:17:12 -0700496{
497 int ret;
498 struct stream_out *out = (struct stream_out *)stream;
499
Paul McLean994ac072016-06-02 15:33:24 -0600500 stream_lock(&out->lock);
Simon Wilson19957a32012-04-06 16:17:12 -0700501 if (out->standby) {
502 ret = start_output_stream(out);
503 if (ret != 0) {
504 goto err;
505 }
506 out->standby = false;
507 }
Eric Laurent05333d42014-08-04 20:29:17 -0700508
jiabin8b265c92020-10-21 15:16:40 -0700509 struct listnode* node;
510 list_for_each(node, &out->alsa_devices) {
511 struct alsa_device_info* device_info =
512 node_to_item(node, struct alsa_device_info, list_node);
513 alsa_device_proxy* proxy = &device_info->proxy;
514 const void * write_buff = buffer;
515 int num_write_buff_bytes = bytes;
516 const int num_device_channels = proxy_get_channel_count(proxy); /* what we told alsa */
517 const int num_req_channels = out->hal_channel_count; /* what we told AudioFlinger */
518 if (num_device_channels != num_req_channels) {
519 /* allocate buffer */
520 const size_t required_conversion_buffer_size =
521 bytes * num_device_channels / num_req_channels;
522 if (required_conversion_buffer_size > out->conversion_buffer_size) {
523 out->conversion_buffer_size = required_conversion_buffer_size;
524 out->conversion_buffer = realloc(out->conversion_buffer,
525 out->conversion_buffer_size);
526 }
527 /* convert data */
528 const audio_format_t audio_format = out_get_format(&(out->stream.common));
529 const unsigned sample_size_in_bytes = audio_bytes_per_sample(audio_format);
530 num_write_buff_bytes =
531 adjust_channels(write_buff, num_req_channels,
532 out->conversion_buffer, num_device_channels,
533 sample_size_in_bytes, num_write_buff_bytes);
534 write_buff = out->conversion_buffer;
Andy Hung03576be2014-07-21 21:16:45 -0700535 }
Paul McLeaneedc92e2013-12-19 15:46:15 -0800536
jiabin8b265c92020-10-21 15:16:40 -0700537 if (write_buff != NULL && num_write_buff_bytes != 0) {
538 proxy_write(proxy, write_buff, num_write_buff_bytes);
539 }
Paul McLeaneedc92e2013-12-19 15:46:15 -0800540 }
Simon Wilson19957a32012-04-06 16:17:12 -0700541
Paul McLean994ac072016-06-02 15:33:24 -0600542 stream_unlock(&out->lock);
Simon Wilson19957a32012-04-06 16:17:12 -0700543
544 return bytes;
545
546err:
Paul McLean994ac072016-06-02 15:33:24 -0600547 stream_unlock(&out->lock);
Simon Wilson19957a32012-04-06 16:17:12 -0700548 if (ret != 0) {
Eric Laurentc5ae6a02014-07-02 13:45:32 -0700549 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Simon Wilson19957a32012-04-06 16:17:12 -0700550 out_get_sample_rate(&stream->common));
551 }
552
553 return bytes;
554}
555
Paul McLean30f41852014-04-16 15:44:20 -0700556static int out_get_render_position(const struct audio_stream_out *stream, uint32_t *dsp_frames)
Simon Wilson19957a32012-04-06 16:17:12 -0700557{
558 return -EINVAL;
559}
560
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700561static int out_get_presentation_position(const struct audio_stream_out *stream,
562 uint64_t *frames, struct timespec *timestamp)
563{
Andy Hungc9515ce2015-08-04 15:05:19 -0700564 struct stream_out *out = (struct stream_out *)stream; // discard const qualifier
Paul McLean994ac072016-06-02 15:33:24 -0600565 stream_lock(&out->lock);
Andy Hungc9515ce2015-08-04 15:05:19 -0700566
jiabin8b265c92020-10-21 15:16:40 -0700567 const struct alsa_device_info* device_info = stream_get_first_alsa_device(&out->alsa_devices);
568 const int ret = device_info == NULL ? -ENODEV :
569 proxy_get_presentation_position(&device_info->proxy, frames, timestamp);
Paul McLean994ac072016-06-02 15:33:24 -0600570 stream_unlock(&out->lock);
Andy Hungc9515ce2015-08-04 15:05:19 -0700571 return ret;
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700572}
573
Simon Wilson19957a32012-04-06 16:17:12 -0700574static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
575{
576 return 0;
577}
578
579static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
580{
581 return 0;
582}
583
Paul McLean30f41852014-04-16 15:44:20 -0700584static int out_get_next_write_timestamp(const struct audio_stream_out *stream, int64_t *timestamp)
Simon Wilson19957a32012-04-06 16:17:12 -0700585{
586 return -EINVAL;
587}
588
Paul McLean76dba682016-06-01 12:29:11 -0600589static int adev_open_output_stream(struct audio_hw_device *hw_dev,
Mike Lockwood46a98092012-04-24 16:41:18 -0700590 audio_io_handle_t handle,
Paul McLean76dba682016-06-01 12:29:11 -0600591 audio_devices_t devicesSpec __unused,
Mike Lockwood46a98092012-04-24 16:41:18 -0700592 audio_output_flags_t flags,
593 struct audio_config *config,
Eric Laurentf5e24692014-07-27 16:14:57 -0700594 struct audio_stream_out **stream_out,
Paul McLean0f1753e2014-12-02 12:36:45 -0700595 const char *address /*__unused*/)
Simon Wilson19957a32012-04-06 16:17:12 -0700596{
Paul McLean76dba682016-06-01 12:29:11 -0600597 ALOGV("adev_open_output_stream() handle:0x%X, devicesSpec:0x%X, flags:0x%X, addr:%s",
598 handle, devicesSpec, flags, address);
Paul McLeaneedc92e2013-12-19 15:46:15 -0800599
Simon Wilson19957a32012-04-06 16:17:12 -0700600 struct stream_out *out;
Simon Wilson19957a32012-04-06 16:17:12 -0700601
602 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
Paul McLean76dba682016-06-01 12:29:11 -0600603 if (out == NULL) {
Simon Wilson19957a32012-04-06 16:17:12 -0700604 return -ENOMEM;
Paul McLean76dba682016-06-01 12:29:11 -0600605 }
Simon Wilson19957a32012-04-06 16:17:12 -0700606
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700607 /* setup function pointers */
Simon Wilson19957a32012-04-06 16:17:12 -0700608 out->stream.common.get_sample_rate = out_get_sample_rate;
609 out->stream.common.set_sample_rate = out_set_sample_rate;
610 out->stream.common.get_buffer_size = out_get_buffer_size;
611 out->stream.common.get_channels = out_get_channels;
612 out->stream.common.get_format = out_get_format;
613 out->stream.common.set_format = out_set_format;
614 out->stream.common.standby = out_standby;
615 out->stream.common.dump = out_dump;
616 out->stream.common.set_parameters = out_set_parameters;
617 out->stream.common.get_parameters = out_get_parameters;
618 out->stream.common.add_audio_effect = out_add_audio_effect;
619 out->stream.common.remove_audio_effect = out_remove_audio_effect;
620 out->stream.get_latency = out_get_latency;
621 out->stream.set_volume = out_set_volume;
622 out->stream.write = out_write;
623 out->stream.get_render_position = out_get_render_position;
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700624 out->stream.get_presentation_position = out_get_presentation_position;
Simon Wilson19957a32012-04-06 16:17:12 -0700625 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
626
Paul McLean994ac072016-06-02 15:33:24 -0600627 stream_lock_init(&out->lock);
Eric Laurent70318092015-06-19 17:49:17 -0700628
Paul McLean76dba682016-06-01 12:29:11 -0600629 out->adev = (struct audio_device *)hw_dev;
Paul McLeancf5310a2018-08-22 14:33:12 -0700630
jiabin8b265c92020-10-21 15:16:40 -0700631 list_init(&out->alsa_devices);
632 struct alsa_device_info *device_info =
633 (struct alsa_device_info *)calloc(1, sizeof(struct alsa_device_info));
634 profile_init(&device_info->profile, PCM_OUT);
Paul McLeanf62d75e2014-07-11 15:14:19 -0700635
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700636 // build this to hand to the alsa_device_proxy
jiabin8b265c92020-10-21 15:16:40 -0700637 struct pcm_config proxy_config = {};
Paul McLeaneedc92e2013-12-19 15:46:15 -0800638
Paul McLean0f1753e2014-12-02 12:36:45 -0700639 /* Pull out the card/device pair */
jiabin8b265c92020-10-21 15:16:40 -0700640 parse_card_device_params(address, &device_info->profile.card, &device_info->profile.device);
Paul McLean0f1753e2014-12-02 12:36:45 -0700641
jiabin8b265c92020-10-21 15:16:40 -0700642 profile_read_device_info(&device_info->profile);
Paul McLean0f1753e2014-12-02 12:36:45 -0700643
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700644 int ret = 0;
Paul McLeaneedc92e2013-12-19 15:46:15 -0800645
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700646 /* Rate */
647 if (config->sample_rate == 0) {
jiabin8b265c92020-10-21 15:16:40 -0700648 proxy_config.rate = profile_get_default_sample_rate(&device_info->profile);
649 } else if (profile_is_sample_rate_valid(&device_info->profile, config->sample_rate)) {
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700650 proxy_config.rate = config->sample_rate;
Paul McLeaneedc92e2013-12-19 15:46:15 -0800651 } else {
jiabin8b265c92020-10-21 15:16:40 -0700652 proxy_config.rate = config->sample_rate =
653 profile_get_default_sample_rate(&device_info->profile);
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700654 ret = -EINVAL;
Paul McLeaneedc92e2013-12-19 15:46:15 -0800655 }
Paul McLeaneedc92e2013-12-19 15:46:15 -0800656
Paul McLeancfdbd6b2018-07-27 11:16:02 -0600657 /* TODO: This is a problem if the input does not support this rate */
Paul McLeancf5310a2018-08-22 14:33:12 -0700658 device_lock(out->adev);
Paul McLean76dba682016-06-01 12:29:11 -0600659 out->adev->device_sample_rate = config->sample_rate;
Paul McLean994ac072016-06-02 15:33:24 -0600660 device_unlock(out->adev);
Paul McLean1d585cc2016-05-24 11:28:10 -0600661
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700662 /* Format */
663 if (config->format == AUDIO_FORMAT_DEFAULT) {
jiabin8b265c92020-10-21 15:16:40 -0700664 proxy_config.format = profile_get_default_format(&device_info->profile);
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700665 config->format = audio_format_from_pcm_format(proxy_config.format);
666 } else {
667 enum pcm_format fmt = pcm_format_from_audio_format(config->format);
jiabin8b265c92020-10-21 15:16:40 -0700668 if (profile_is_format_valid(&device_info->profile, fmt)) {
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700669 proxy_config.format = fmt;
670 } else {
jiabin8b265c92020-10-21 15:16:40 -0700671 proxy_config.format = profile_get_default_format(&device_info->profile);
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700672 config->format = audio_format_from_pcm_format(proxy_config.format);
673 ret = -EINVAL;
674 }
675 }
676
677 /* Channels */
Paul McLean64345f82016-06-06 13:26:05 -0600678 bool calc_mask = false;
679 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
680 /* query case */
jiabin8b265c92020-10-21 15:16:40 -0700681 out->hal_channel_count = profile_get_default_channel_count(&device_info->profile);
Paul McLean64345f82016-06-06 13:26:05 -0600682 calc_mask = true;
Andy Hung182ddc72015-05-05 23:37:30 -0700683 } else {
Paul McLean64345f82016-06-06 13:26:05 -0600684 /* explicit case */
685 out->hal_channel_count = audio_channel_count_from_out_mask(config->channel_mask);
Andy Hung182ddc72015-05-05 23:37:30 -0700686 }
Paul McLean698dbd72015-11-03 12:24:30 -0800687
Paul McLean64345f82016-06-06 13:26:05 -0600688 /* The Framework is currently limited to no more than this number of channels */
689 if (out->hal_channel_count > FCC_8) {
690 out->hal_channel_count = FCC_8;
691 calc_mask = true;
692 }
693
694 if (calc_mask) {
695 /* need to calculate the mask from channel count either because this is the query case
jiabin8b265c92020-10-21 15:16:40 -0700696 * or the specified mask isn't valid for this device, or is more than the FW can handle */
Paul McLean64345f82016-06-06 13:26:05 -0600697 config->channel_mask = out->hal_channel_count <= FCC_2
jiabin8b265c92020-10-21 15:16:40 -0700698 /* position mask for mono and stereo*/
699 ? audio_channel_out_mask_from_count(out->hal_channel_count)
700 /* otherwise indexed */
701 : audio_channel_mask_for_index_assignment_from_count(out->hal_channel_count);
Paul McLean64345f82016-06-06 13:26:05 -0600702 }
703
Andy Hung182ddc72015-05-05 23:37:30 -0700704 out->hal_channel_mask = config->channel_mask;
705
Paul McLean64345f82016-06-06 13:26:05 -0600706 // Validate the "logical" channel count against support in the "actual" profile.
707 // if they differ, choose the "actual" number of channels *closest* to the "logical".
708 // and store THAT in proxy_config.channels
Paul McLeancf5310a2018-08-22 14:33:12 -0700709 proxy_config.channels =
jiabin8b265c92020-10-21 15:16:40 -0700710 profile_get_closest_channel_count(&device_info->profile, out->hal_channel_count);
711 proxy_prepare(&device_info->proxy, &device_info->profile, &proxy_config);
712
713 list_add_tail(&out->alsa_devices, &device_info->list_node);
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700714
Paul McLean96c4d302017-12-05 09:50:26 -0800715 /* TODO The retry mechanism isn't implemented in AudioPolicyManager/AudioFlinger
716 * So clear any errors that may have occurred above.
717 */
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700718 ret = 0;
719
Paul McLeaneedc92e2013-12-19 15:46:15 -0800720 out->conversion_buffer = NULL;
721 out->conversion_buffer_size = 0;
Simon Wilson19957a32012-04-06 16:17:12 -0700722
723 out->standby = true;
724
Paul McLean6a75e4e2016-05-25 14:09:02 -0600725 /* Save the stream for adev_dump() */
Paul McLean76dba682016-06-01 12:29:11 -0600726 adev_add_stream_to_list(out->adev, &out->adev->output_stream_list, &out->list_node);
Paul McLean6a75e4e2016-05-25 14:09:02 -0600727
Simon Wilson19957a32012-04-06 16:17:12 -0700728 *stream_out = &out->stream;
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700729
730 return ret;
Simon Wilson19957a32012-04-06 16:17:12 -0700731}
732
Paul McLean76dba682016-06-01 12:29:11 -0600733static void adev_close_output_stream(struct audio_hw_device *hw_dev,
Simon Wilson19957a32012-04-06 16:17:12 -0700734 struct audio_stream_out *stream)
735{
736 struct stream_out *out = (struct stream_out *)stream;
Paul McLean6a75e4e2016-05-25 14:09:02 -0600737
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700738 /* Close the pcm device */
Simon Wilson19957a32012-04-06 16:17:12 -0700739 out_standby(&stream->common);
Paul McLeaneedc92e2013-12-19 15:46:15 -0800740
741 free(out->conversion_buffer);
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700742
Paul McLeaneedc92e2013-12-19 15:46:15 -0800743 out->conversion_buffer = NULL;
744 out->conversion_buffer_size = 0;
745
jiabin8b265c92020-10-21 15:16:40 -0700746 struct listnode *node, *temp;
747 struct alsa_device_info *item = NULL;
748 stream_lock(&out->lock);
749 list_for_each_safe (node, temp, &out->alsa_devices) {
750 item = node_to_item(node, struct alsa_device_info, list_node);
751 if (item != NULL) {
752 list_remove(&item->list_node);
753 free(item);
754 }
755 }
756 stream_unlock(&out->lock);
757
Paul McLeancf5310a2018-08-22 14:33:12 -0700758 adev_remove_stream_from_list(out->adev, &out->list_node);
759
Paul McLean994ac072016-06-02 15:33:24 -0600760 device_lock(out->adev);
Paul McLean76dba682016-06-01 12:29:11 -0600761 out->adev->device_sample_rate = 0;
Paul McLean994ac072016-06-02 15:33:24 -0600762 device_unlock(out->adev);
Paul McLean1d585cc2016-05-24 11:28:10 -0600763
Simon Wilson19957a32012-04-06 16:17:12 -0700764 free(stream);
765}
766
Paul McLean76dba682016-06-01 12:29:11 -0600767static size_t adev_get_input_buffer_size(const struct audio_hw_device *hw_dev,
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700768 const struct audio_config *config)
769{
770 /* TODO This needs to be calculated based on format/channels/rate */
771 return 320;
772}
773
774/*
775 * IN functions
776 */
777static uint32_t in_get_sample_rate(const struct audio_stream *stream)
778{
jiabin8b265c92020-10-21 15:16:40 -0700779 struct alsa_device_info *device_info = stream_get_first_alsa_device(
780 &((const struct stream_in *)stream)->alsa_devices);
781 if (device_info == NULL) {
782 ALOGW("%s device info is null", __func__);
783 return 0;
784 }
785 uint32_t rate = proxy_get_sample_rate(&device_info->proxy);
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700786 ALOGV("in_get_sample_rate() = %d", rate);
787 return rate;
788}
789
790static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
791{
792 ALOGV("in_set_sample_rate(%d) - NOPE", rate);
793 return -ENOSYS;
794}
795
796static size_t in_get_buffer_size(const struct audio_stream *stream)
797{
798 const struct stream_in * in = ((const struct stream_in*)stream);
jiabin8b265c92020-10-21 15:16:40 -0700799 struct alsa_device_info *device_info = stream_get_first_alsa_device(&in->alsa_devices);
800 if (device_info == NULL) {
801 ALOGW("%s device info is null", __func__);
802 return 0;
803 }
804 return proxy_get_period_size(&device_info->proxy) * audio_stream_in_frame_size(&(in->stream));
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700805}
806
807static uint32_t in_get_channels(const struct audio_stream *stream)
808{
Paul McLean2cfd81b2014-09-15 12:32:23 -0700809 const struct stream_in *in = (const struct stream_in*)stream;
Andy Hung780f1f82015-04-22 22:14:39 -0700810 return in->hal_channel_mask;
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700811}
812
813static audio_format_t in_get_format(const struct audio_stream *stream)
814{
jiabin8b265c92020-10-21 15:16:40 -0700815 struct alsa_device_info *device_info = stream_get_first_alsa_device(
816 &((const struct stream_in *)stream)->alsa_devices);
817 if (device_info == NULL) {
818 ALOGW("%s device info is null", __func__);
819 return AUDIO_FORMAT_DEFAULT;
820 }
821 alsa_device_proxy *proxy = &device_info->proxy;
Andy Hung780f1f82015-04-22 22:14:39 -0700822 audio_format_t format = audio_format_from_pcm_format(proxy_get_format(proxy));
823 return format;
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700824}
825
826static int in_set_format(struct audio_stream *stream, audio_format_t format)
827{
828 ALOGV("in_set_format(%d) - NOPE", format);
829
830 return -ENOSYS;
831}
832
833static int in_standby(struct audio_stream *stream)
834{
835 struct stream_in *in = (struct stream_in *)stream;
836
Paul McLean994ac072016-06-02 15:33:24 -0600837 stream_lock(&in->lock);
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700838 if (!in->standby) {
jiabin8b265c92020-10-21 15:16:40 -0700839 struct listnode *node;
840 list_for_each (node, &in->alsa_devices) {
841 struct alsa_device_info *device_info =
842 node_to_item(node, struct alsa_device_info, list_node);
843 proxy_close(&device_info->proxy);
844 }
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700845 in->standby = true;
846 }
Paul McLean994ac072016-06-02 15:33:24 -0600847 stream_unlock(&in->lock);
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700848
849 return 0;
850}
851
852static int in_dump(const struct audio_stream *stream, int fd)
853{
Paul McLean6a75e4e2016-05-25 14:09:02 -0600854 const struct stream_in* in_stream = (const struct stream_in*)stream;
855 if (in_stream != NULL) {
jiabin8b265c92020-10-21 15:16:40 -0700856 stream_dump_alsa_devices(&in_stream->alsa_devices, fd);
Paul McLean6a75e4e2016-05-25 14:09:02 -0600857 }
858
859 return 0;
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700860}
861
862static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
863{
Paul McLean65ec72b2015-02-18 09:13:24 -0800864 ALOGV("in_set_parameters() keys:%s", kvpairs);
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700865
866 struct stream_in *in = (struct stream_in *)stream;
867
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700868 int ret_value = 0;
Eric Laurent05333d42014-08-04 20:29:17 -0700869 int card = -1;
870 int device = -1;
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700871
Paul McLean65ec72b2015-02-18 09:13:24 -0800872 if (!parse_card_device_params(kvpairs, &card, &device)) {
873 // nothing to do
874 return ret_value;
875 }
876
Paul McLean994ac072016-06-02 15:33:24 -0600877 stream_lock(&in->lock);
878 device_lock(in->adev);
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700879
jiabin8b265c92020-10-21 15:16:40 -0700880 struct alsa_device_info* device_info = stream_get_first_alsa_device(&in->alsa_devices);
881
882 if (card >= 0 && device >= 0 &&
883 device_info != NULL && !profile_is_cached_for(&device_info->profile, card, device)) {
Paul McLeancf5310a2018-08-22 14:33:12 -0700884 /* cannot read pcm device info if capture is active, or more than one open stream */
Andy Hungb10ce6d2017-10-27 19:37:58 -0700885 if (!in->standby || in->adev->inputs_open > 1)
Eric Laurent05333d42014-08-04 20:29:17 -0700886 ret_value = -ENOSYS;
887 else {
jiabin8b265c92020-10-21 15:16:40 -0700888 int saved_card = device_info->profile.card;
889 int saved_device = device_info->profile.device;
890 device_info->profile.card = card;
891 device_info->profile.device = device;
892 ret_value = profile_read_device_info(&device_info->profile) ? 0 : -EINVAL;
Eric Laurent05333d42014-08-04 20:29:17 -0700893 if (ret_value != 0) {
Paul McLeancf5310a2018-08-22 14:33:12 -0700894 ALOGE("Can't read device profile. card:%d, device:%d", card, device);
jiabin8b265c92020-10-21 15:16:40 -0700895 device_info->profile.card = saved_card;
896 device_info->profile.device = saved_device;
Eric Laurent05333d42014-08-04 20:29:17 -0700897 }
898 }
Paul McLean2c6196f2014-08-20 16:50:25 -0700899 }
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700900
Paul McLean994ac072016-06-02 15:33:24 -0600901 device_unlock(in->adev);
902 stream_unlock(&in->lock);
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700903
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700904 return ret_value;
905}
906
907static char * in_get_parameters(const struct audio_stream *stream, const char *keys)
908{
909 struct stream_in *in = (struct stream_in *)stream;
910
Paul McLean994ac072016-06-02 15:33:24 -0600911 stream_lock(&in->lock);
jiabin8b265c92020-10-21 15:16:40 -0700912 struct alsa_device_info *device_info = stream_get_first_alsa_device(&in->alsa_devices);
913 char *params_str = NULL;
914 if (device_info != NULL) {
915 params_str = device_get_parameters(&device_info->profile, keys);
916 }
Paul McLean994ac072016-06-02 15:33:24 -0600917 stream_unlock(&in->lock);
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700918
919 return params_str;
920}
921
922static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
923{
924 return 0;
925}
926
927static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
928{
929 return 0;
930}
931
932static int in_set_gain(struct audio_stream_in *stream, float gain)
933{
934 return 0;
935}
936
937/* must be called with hw device and output stream mutexes locked */
938static int start_input_stream(struct stream_in *in)
939{
jiabin8b265c92020-10-21 15:16:40 -0700940 // Only care about the first device as only one input device is allowed.
941 struct alsa_device_info *device_info = stream_get_first_alsa_device(&in->alsa_devices);
942 if (device_info == NULL) {
943 return -ENODEV;
944 }
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700945
jiabin8b265c92020-10-21 15:16:40 -0700946 ALOGV("start_input_stream(card:%d device:%d)",
947 device_info->profile.card, device_info->profile.device);
948 return proxy_open(&device_info->proxy);
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700949}
950
951/* TODO mutex stuff here (see out_write) */
952static ssize_t in_read(struct audio_stream_in *stream, void* buffer, size_t bytes)
953{
954 size_t num_read_buff_bytes = 0;
955 void * read_buff = buffer;
956 void * out_buff = buffer;
Pavan Chikkala83b47a62015-01-09 12:21:13 -0800957 int ret = 0;
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700958
959 struct stream_in * in = (struct stream_in *)stream;
960
Paul McLean994ac072016-06-02 15:33:24 -0600961 stream_lock(&in->lock);
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700962 if (in->standby) {
Eric Laurent70318092015-06-19 17:49:17 -0700963 ret = start_input_stream(in);
Eric Laurent70318092015-06-19 17:49:17 -0700964 if (ret != 0) {
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700965 goto err;
966 }
967 in->standby = false;
968 }
969
jiabin8b265c92020-10-21 15:16:40 -0700970 // Only care about the first device as only one input device is allowed.
971 struct alsa_device_info *device_info = stream_get_first_alsa_device(&in->alsa_devices);
972 if (device_info == NULL) {
973 return 0;
974 }
975
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700976 /*
977 * OK, we need to figure out how much data to read to be able to output the requested
978 * number of bytes in the HAL format (16-bit, stereo).
979 */
980 num_read_buff_bytes = bytes;
jiabin8b265c92020-10-21 15:16:40 -0700981 int num_device_channels = proxy_get_channel_count(&device_info->proxy); /* what we told Alsa */
Andy Hung780f1f82015-04-22 22:14:39 -0700982 int num_req_channels = in->hal_channel_count; /* what we told AudioFlinger */
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700983
984 if (num_device_channels != num_req_channels) {
985 num_read_buff_bytes = (num_device_channels * num_read_buff_bytes) / num_req_channels;
986 }
987
Paul McLeanc88e6ae2014-07-16 09:48:34 -0700988 /* Setup/Realloc the conversion buffer (if necessary). */
989 if (num_read_buff_bytes != bytes) {
990 if (num_read_buff_bytes > in->conversion_buffer_size) {
991 /*TODO Remove this when AudioPolicyManger/AudioFlinger support arbitrary formats
992 (and do these conversions themselves) */
993 in->conversion_buffer_size = num_read_buff_bytes;
994 in->conversion_buffer = realloc(in->conversion_buffer, in->conversion_buffer_size);
995 }
996 read_buff = in->conversion_buffer;
997 }
998
jiabin8b265c92020-10-21 15:16:40 -0700999 ret = proxy_read(&device_info->proxy, read_buff, num_read_buff_bytes);
Pavan Chikkala83b47a62015-01-09 12:21:13 -08001000 if (ret == 0) {
Paul McLeanc88e6ae2014-07-16 09:48:34 -07001001 if (num_device_channels != num_req_channels) {
1002 // ALOGV("chans dev:%d req:%d", num_device_channels, num_req_channels);
1003
1004 out_buff = buffer;
1005 /* Num Channels conversion */
1006 if (num_device_channels != num_req_channels) {
1007 audio_format_t audio_format = in_get_format(&(in->stream.common));
1008 unsigned sample_size_in_bytes = audio_bytes_per_sample(audio_format);
1009
1010 num_read_buff_bytes =
1011 adjust_channels(read_buff, num_device_channels,
1012 out_buff, num_req_channels,
1013 sample_size_in_bytes, num_read_buff_bytes);
1014 }
1015 }
Eric Laurent253def92014-09-14 12:18:18 -07001016
Paul McLean76dba682016-06-01 12:29:11 -06001017 /* no need to acquire in->adev->lock to read mic_muted here as we don't change its state */
1018 if (num_read_buff_bytes > 0 && in->adev->mic_muted)
Eric Laurent253def92014-09-14 12:18:18 -07001019 memset(buffer, 0, num_read_buff_bytes);
Viswanath L8c7e1112014-10-31 13:07:39 +05301020 } else {
Eric Laurente6499422015-01-09 17:03:27 -08001021 num_read_buff_bytes = 0; // reset the value after USB headset is unplugged
Paul McLeanc88e6ae2014-07-16 09:48:34 -07001022 }
1023
1024err:
Paul McLean994ac072016-06-02 15:33:24 -06001025 stream_unlock(&in->lock);
Paul McLeanc88e6ae2014-07-16 09:48:34 -07001026 return num_read_buff_bytes;
1027}
1028
1029static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
1030{
1031 return 0;
1032}
1033
Andy Hungfa6b4a62018-06-04 19:14:22 -07001034static int in_get_capture_position(const struct audio_stream_in *stream,
1035 int64_t *frames, int64_t *time)
1036{
1037 struct stream_in *in = (struct stream_in *)stream; // discard const qualifier
1038 stream_lock(&in->lock);
1039
jiabin8b265c92020-10-21 15:16:40 -07001040 struct alsa_device_info *device_info = stream_get_first_alsa_device(&in->alsa_devices);
1041
1042 const int ret = device_info == NULL ? -ENODEV
1043 : proxy_get_capture_position(&device_info->proxy, frames, time);
Andy Hungfa6b4a62018-06-04 19:14:22 -07001044
1045 stream_unlock(&in->lock);
1046 return ret;
1047}
1048
Paul McLeanfa3ae3e2018-12-12 09:57:02 -08001049static int in_get_active_microphones(const struct audio_stream_in *stream,
1050 struct audio_microphone_characteristic_t *mic_array,
1051 size_t *mic_count) {
1052 (void)stream;
1053 (void)mic_array;
1054 (void)mic_count;
1055
1056 return -ENOSYS;
1057}
1058
1059static int in_set_microphone_direction(const struct audio_stream_in *stream,
1060 audio_microphone_direction_t dir) {
1061 (void)stream;
1062 (void)dir;
1063 ALOGV("---- in_set_microphone_direction()");
1064 return -ENOSYS;
1065}
1066
1067static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
1068 (void)zoom;
1069 ALOGV("---- in_set_microphone_field_dimension()");
1070 return -ENOSYS;
1071}
1072
Paul McLean76dba682016-06-01 12:29:11 -06001073static int adev_open_input_stream(struct audio_hw_device *hw_dev,
Paul McLeanc88e6ae2014-07-16 09:48:34 -07001074 audio_io_handle_t handle,
Paul McLean76dba682016-06-01 12:29:11 -06001075 audio_devices_t devicesSpec __unused,
Paul McLeanc88e6ae2014-07-16 09:48:34 -07001076 struct audio_config *config,
1077 struct audio_stream_in **stream_in,
Eric Laurentf5e24692014-07-27 16:14:57 -07001078 audio_input_flags_t flags __unused,
Eric Laurent981f7742017-05-03 12:44:26 -07001079 const char *address,
Eric Laurentf5e24692014-07-27 16:14:57 -07001080 audio_source_t source __unused)
Paul McLeanc88e6ae2014-07-16 09:48:34 -07001081{
Paul McLean1d585cc2016-05-24 11:28:10 -06001082 ALOGV("adev_open_input_stream() rate:%" PRIu32 ", chanMask:0x%" PRIX32 ", fmt:%" PRIu8,
Paul McLeanc88e6ae2014-07-16 09:48:34 -07001083 config->sample_rate, config->channel_mask, config->format);
1084
Andy Hungb10ce6d2017-10-27 19:37:58 -07001085 /* Pull out the card/device pair */
1086 int32_t card, device;
1087 if (!parse_card_device_params(address, &card, &device)) {
1088 ALOGW("%s fail - invalid address %s", __func__, address);
1089 *stream_in = NULL;
1090 return -EINVAL;
1091 }
Paul McLeanc88e6ae2014-07-16 09:48:34 -07001092
Andy Hungb10ce6d2017-10-27 19:37:58 -07001093 struct stream_in * const in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Paul McLean76dba682016-06-01 12:29:11 -06001094 if (in == NULL) {
Andy Hungb10ce6d2017-10-27 19:37:58 -07001095 *stream_in = NULL;
Paul McLeanc88e6ae2014-07-16 09:48:34 -07001096 return -ENOMEM;
Paul McLean76dba682016-06-01 12:29:11 -06001097 }
Paul McLeanc88e6ae2014-07-16 09:48:34 -07001098
1099 /* setup function pointers */
1100 in->stream.common.get_sample_rate = in_get_sample_rate;
1101 in->stream.common.set_sample_rate = in_set_sample_rate;
1102 in->stream.common.get_buffer_size = in_get_buffer_size;
1103 in->stream.common.get_channels = in_get_channels;
1104 in->stream.common.get_format = in_get_format;
1105 in->stream.common.set_format = in_set_format;
1106 in->stream.common.standby = in_standby;
1107 in->stream.common.dump = in_dump;
1108 in->stream.common.set_parameters = in_set_parameters;
1109 in->stream.common.get_parameters = in_get_parameters;
1110 in->stream.common.add_audio_effect = in_add_audio_effect;
1111 in->stream.common.remove_audio_effect = in_remove_audio_effect;
1112
1113 in->stream.set_gain = in_set_gain;
1114 in->stream.read = in_read;
1115 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hungfa6b4a62018-06-04 19:14:22 -07001116 in->stream.get_capture_position = in_get_capture_position;
Paul McLeanc88e6ae2014-07-16 09:48:34 -07001117
Paul McLeanfa3ae3e2018-12-12 09:57:02 -08001118 in->stream.get_active_microphones = in_get_active_microphones;
1119 in->stream.set_microphone_direction = in_set_microphone_direction;
1120 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
1121
Paul McLean994ac072016-06-02 15:33:24 -06001122 stream_lock_init(&in->lock);
Eric Laurent70318092015-06-19 17:49:17 -07001123
Paul McLean76dba682016-06-01 12:29:11 -06001124 in->adev = (struct audio_device *)hw_dev;
Paul McLeanc88e6ae2014-07-16 09:48:34 -07001125
jiabin8b265c92020-10-21 15:16:40 -07001126 list_init(&in->alsa_devices);
1127 struct alsa_device_info *device_info =
1128 (struct alsa_device_info *)calloc(1, sizeof(struct alsa_device_info));
1129 profile_init(&device_info->profile, PCM_IN);
Paul McLeanc88e6ae2014-07-16 09:48:34 -07001130
1131 struct pcm_config proxy_config;
Paul McLean2c6196f2014-08-20 16:50:25 -07001132 memset(&proxy_config, 0, sizeof(proxy_config));
Paul McLeanc88e6ae2014-07-16 09:48:34 -07001133
Andy Hungb10ce6d2017-10-27 19:37:58 -07001134 int ret = 0;
Paul McLeancf5310a2018-08-22 14:33:12 -07001135 device_lock(in->adev);
1136 int num_open_inputs = in->adev->inputs_open;
1137 device_unlock(in->adev);
1138
Andy Hungb10ce6d2017-10-27 19:37:58 -07001139 /* Check if an input stream is already open */
Paul McLeancf5310a2018-08-22 14:33:12 -07001140 if (num_open_inputs > 0) {
jiabin8b265c92020-10-21 15:16:40 -07001141 if (!profile_is_cached_for(&device_info->profile, card, device)) {
Andy Hungb10ce6d2017-10-27 19:37:58 -07001142 ALOGW("%s fail - address card:%d device:%d doesn't match existing profile",
1143 __func__, card, device);
1144 ret = -EINVAL;
1145 }
1146 } else {
1147 /* Read input profile only if necessary */
jiabin8b265c92020-10-21 15:16:40 -07001148 device_info->profile.card = card;
1149 device_info->profile.device = device;
1150 if (!profile_read_device_info(&device_info->profile)) {
Andy Hungb10ce6d2017-10-27 19:37:58 -07001151 ALOGW("%s fail - cannot read profile", __func__);
1152 ret = -EINVAL;
1153 }
1154 }
1155 if (ret != 0) {
Andy Hungb10ce6d2017-10-27 19:37:58 -07001156 free(in);
1157 *stream_in = NULL;
1158 return ret;
1159 }
Paul McLean0f1753e2014-12-02 12:36:45 -07001160
Paul McLeanc88e6ae2014-07-16 09:48:34 -07001161 /* Rate */
Paul McLeancfdbd6b2018-07-27 11:16:02 -06001162 int request_config_rate = config->sample_rate;
Paul McLeanc88e6ae2014-07-16 09:48:34 -07001163 if (config->sample_rate == 0) {
jiabin8b265c92020-10-21 15:16:40 -07001164 config->sample_rate = profile_get_default_sample_rate(&device_info->profile);
Paul McLean9a1c3052016-05-25 13:30:54 -06001165 }
1166
Paul McLeancfdbd6b2018-07-27 11:16:02 -06001167 if (in->adev->device_sample_rate != 0 && /* we are playing, so lock the rate if possible */
Paul McLean76dba682016-06-01 12:29:11 -06001168 in->adev->device_sample_rate >= RATELOCK_THRESHOLD) {/* but only for high sample rates */
Paul McLeancfdbd6b2018-07-27 11:16:02 -06001169 if (config->sample_rate != in->adev->device_sample_rate) {
jiabin8b265c92020-10-21 15:16:40 -07001170 unsigned highest_rate = profile_get_highest_sample_rate(&device_info->profile);
Paul McLeancfdbd6b2018-07-27 11:16:02 -06001171 if (highest_rate == 0) {
1172 ret = -EINVAL; /* error with device */
1173 } else {
1174 proxy_config.rate = config->sample_rate =
1175 min(highest_rate, in->adev->device_sample_rate);
1176 if (request_config_rate != 0 && proxy_config.rate != config->sample_rate) {
1177 /* Changing the requested rate */
1178 ret = -EINVAL;
1179 } else {
1180 /* Everything AOK! */
1181 ret = 0;
1182 }
1183 }
1184 }
jiabin8b265c92020-10-21 15:16:40 -07001185 } else if (profile_is_sample_rate_valid(&device_info->profile, config->sample_rate)) {
Eric Laurent981f7742017-05-03 12:44:26 -07001186 proxy_config.rate = config->sample_rate;
Paul McLeanc88e6ae2014-07-16 09:48:34 -07001187 } else {
jiabin8b265c92020-10-21 15:16:40 -07001188 proxy_config.rate = config->sample_rate =
1189 profile_get_default_sample_rate(&device_info->profile);
Paul McLeanc88e6ae2014-07-16 09:48:34 -07001190 ret = -EINVAL;
1191 }
Paul McLeancfdbd6b2018-07-27 11:16:02 -06001192
Paul McLeanc88e6ae2014-07-16 09:48:34 -07001193 /* Format */
Paul McLeanc88e6ae2014-07-16 09:48:34 -07001194 if (config->format == AUDIO_FORMAT_DEFAULT) {
jiabin8b265c92020-10-21 15:16:40 -07001195 proxy_config.format = profile_get_default_format(&device_info->profile);
Andy Hung780f1f82015-04-22 22:14:39 -07001196 config->format = audio_format_from_pcm_format(proxy_config.format);
Paul McLeanc88e6ae2014-07-16 09:48:34 -07001197 } else {
Andy Hung780f1f82015-04-22 22:14:39 -07001198 enum pcm_format fmt = pcm_format_from_audio_format(config->format);
jiabin8b265c92020-10-21 15:16:40 -07001199 if (profile_is_format_valid(&device_info->profile, fmt)) {
Andy Hung780f1f82015-04-22 22:14:39 -07001200 proxy_config.format = fmt;
1201 } else {
jiabin8b265c92020-10-21 15:16:40 -07001202 proxy_config.format = profile_get_default_format(&device_info->profile);
Andy Hung780f1f82015-04-22 22:14:39 -07001203 config->format = audio_format_from_pcm_format(proxy_config.format);
1204 ret = -EINVAL;
1205 }
Paul McLeanc88e6ae2014-07-16 09:48:34 -07001206 }
1207
Paul McLean2cfd81b2014-09-15 12:32:23 -07001208 /* Channels */
Paul McLean64345f82016-06-06 13:26:05 -06001209 bool calc_mask = false;
1210 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
1211 /* query case */
jiabin8b265c92020-10-21 15:16:40 -07001212 in->hal_channel_count = profile_get_default_channel_count(&device_info->profile);
Paul McLean64345f82016-06-06 13:26:05 -06001213 calc_mask = true;
Andy Hung780f1f82015-04-22 22:14:39 -07001214 } else {
Paul McLean64345f82016-06-06 13:26:05 -06001215 /* explicit case */
Andy Hung780f1f82015-04-22 22:14:39 -07001216 in->hal_channel_count = audio_channel_count_from_in_mask(config->channel_mask);
1217 }
Paul McLeanc88e6ae2014-07-16 09:48:34 -07001218
Paul McLean64345f82016-06-06 13:26:05 -06001219 /* The Framework is currently limited to no more than this number of channels */
1220 if (in->hal_channel_count > FCC_8) {
1221 in->hal_channel_count = FCC_8;
1222 calc_mask = true;
1223 }
Paul McLeanc88e6ae2014-07-16 09:48:34 -07001224
Paul McLean64345f82016-06-06 13:26:05 -06001225 if (calc_mask) {
1226 /* need to calculate the mask from channel count either because this is the query case
jiabin8b265c92020-10-21 15:16:40 -07001227 * or the specified mask isn't valid for this device, or is more than the FW can handle */
Paul McLean64345f82016-06-06 13:26:05 -06001228 in->hal_channel_mask = in->hal_channel_count <= FCC_2
1229 /* position mask for mono & stereo */
1230 ? audio_channel_in_mask_from_count(in->hal_channel_count)
1231 /* otherwise indexed */
1232 : audio_channel_mask_for_index_assignment_from_count(in->hal_channel_count);
Paul McLeanc88e6ae2014-07-16 09:48:34 -07001233
Paul McLean64345f82016-06-06 13:26:05 -06001234 // if we change the mask...
1235 if (in->hal_channel_mask != config->channel_mask &&
1236 config->channel_mask != AUDIO_CHANNEL_NONE) {
1237 config->channel_mask = in->hal_channel_mask;
1238 ret = -EINVAL;
1239 }
1240 } else {
1241 in->hal_channel_mask = config->channel_mask;
1242 }
Paul McLean6a75e4e2016-05-25 14:09:02 -06001243
Paul McLean64345f82016-06-06 13:26:05 -06001244 if (ret == 0) {
1245 // Validate the "logical" channel count against support in the "actual" profile.
1246 // if they differ, choose the "actual" number of channels *closest* to the "logical".
1247 // and store THAT in proxy_config.channels
1248 proxy_config.channels =
jiabin8b265c92020-10-21 15:16:40 -07001249 profile_get_closest_channel_count(&device_info->profile, in->hal_channel_count);
1250 ret = proxy_prepare(&device_info->proxy, &device_info->profile, &proxy_config);
Eric Laurent981f7742017-05-03 12:44:26 -07001251 if (ret == 0) {
1252 in->standby = true;
Paul McLeanc88e6ae2014-07-16 09:48:34 -07001253
Eric Laurent981f7742017-05-03 12:44:26 -07001254 in->conversion_buffer = NULL;
1255 in->conversion_buffer_size = 0;
Paul McLean64345f82016-06-06 13:26:05 -06001256
Eric Laurent981f7742017-05-03 12:44:26 -07001257 *stream_in = &in->stream;
Paul McLean64345f82016-06-06 13:26:05 -06001258
Eric Laurent981f7742017-05-03 12:44:26 -07001259 /* Save this for adev_dump() */
1260 adev_add_stream_to_list(in->adev, &in->adev->input_stream_list, &in->list_node);
1261 } else {
1262 ALOGW("proxy_prepare error %d", ret);
jiabin8b265c92020-10-21 15:16:40 -07001263 unsigned channel_count = proxy_get_channel_count(&device_info->proxy);
Eric Laurent981f7742017-05-03 12:44:26 -07001264 config->channel_mask = channel_count <= FCC_2
1265 ? audio_channel_in_mask_from_count(channel_count)
1266 : audio_channel_mask_for_index_assignment_from_count(channel_count);
jiabin8b265c92020-10-21 15:16:40 -07001267 config->format = audio_format_from_pcm_format(proxy_get_format(&device_info->proxy));
1268 config->sample_rate = proxy_get_sample_rate(&device_info->proxy);
Eric Laurent981f7742017-05-03 12:44:26 -07001269 }
1270 }
Paul McLean64345f82016-06-06 13:26:05 -06001271
Eric Laurent981f7742017-05-03 12:44:26 -07001272 if (ret != 0) {
Paul McLean64345f82016-06-06 13:26:05 -06001273 // Deallocate this stream on error, because AudioFlinger won't call
1274 // adev_close_input_stream() in this case.
1275 *stream_in = NULL;
1276 free(in);
Mikhail Naganov1d08a562020-03-26 13:18:12 -07001277 return ret;
Paul McLean64345f82016-06-06 13:26:05 -06001278 }
Paul McLeanc88e6ae2014-07-16 09:48:34 -07001279
jiabin8b265c92020-10-21 15:16:40 -07001280 list_add_tail(&in->alsa_devices, &device_info->list_node);
1281
Andy Hungb10ce6d2017-10-27 19:37:58 -07001282 device_lock(in->adev);
1283 ++in->adev->inputs_open;
1284 device_unlock(in->adev);
1285
Paul McLeanc88e6ae2014-07-16 09:48:34 -07001286 return ret;
1287}
1288
Paul McLean76dba682016-06-01 12:29:11 -06001289static void adev_close_input_stream(struct audio_hw_device *hw_dev,
1290 struct audio_stream_in *stream)
Paul McLeanc88e6ae2014-07-16 09:48:34 -07001291{
1292 struct stream_in *in = (struct stream_in *)stream;
Paul McLean6a75e4e2016-05-25 14:09:02 -06001293
Paul McLean76dba682016-06-01 12:29:11 -06001294 adev_remove_stream_from_list(in->adev, &in->list_node);
Paul McLeanc88e6ae2014-07-16 09:48:34 -07001295
Andy Hungb10ce6d2017-10-27 19:37:58 -07001296 device_lock(in->adev);
1297 --in->adev->inputs_open;
jiabin8b265c92020-10-21 15:16:40 -07001298 struct alsa_device_info *device_info = stream_get_first_alsa_device(&in->alsa_devices);
1299 if (device_info != NULL) {
1300 ALOGV("adev_close_input_stream(c:%d d:%d)",
1301 device_info->profile.card, device_info->profile.device);
1302 }
Andy Hungb10ce6d2017-10-27 19:37:58 -07001303 LOG_ALWAYS_FATAL_IF(in->adev->inputs_open < 0,
1304 "invalid inputs_open: %d", in->adev->inputs_open);
1305 device_unlock(in->adev);
1306
Paul McLeanc88e6ae2014-07-16 09:48:34 -07001307 /* Close the pcm device */
1308 in_standby(&stream->common);
1309
1310 free(in->conversion_buffer);
1311
1312 free(stream);
1313}
1314
1315/*
1316 * ADEV Functions
1317 */
Paul McLean76dba682016-06-01 12:29:11 -06001318static int adev_set_parameters(struct audio_hw_device *hw_dev, const char *kvpairs)
Simon Wilson19957a32012-04-06 16:17:12 -07001319{
1320 return 0;
1321}
1322
Paul McLean76dba682016-06-01 12:29:11 -06001323static char * adev_get_parameters(const struct audio_hw_device *hw_dev, const char *keys)
Simon Wilson19957a32012-04-06 16:17:12 -07001324{
1325 return strdup("");
1326}
1327
Paul McLean76dba682016-06-01 12:29:11 -06001328static int adev_init_check(const struct audio_hw_device *hw_dev)
Simon Wilson19957a32012-04-06 16:17:12 -07001329{
1330 return 0;
1331}
1332
Paul McLean76dba682016-06-01 12:29:11 -06001333static int adev_set_voice_volume(struct audio_hw_device *hw_dev, float volume)
Simon Wilson19957a32012-04-06 16:17:12 -07001334{
1335 return -ENOSYS;
1336}
1337
Paul McLean76dba682016-06-01 12:29:11 -06001338static int adev_set_master_volume(struct audio_hw_device *hw_dev, float volume)
Simon Wilson19957a32012-04-06 16:17:12 -07001339{
1340 return -ENOSYS;
1341}
1342
Paul McLean76dba682016-06-01 12:29:11 -06001343static int adev_set_mode(struct audio_hw_device *hw_dev, audio_mode_t mode)
Simon Wilson19957a32012-04-06 16:17:12 -07001344{
1345 return 0;
1346}
1347
Paul McLean76dba682016-06-01 12:29:11 -06001348static int adev_set_mic_mute(struct audio_hw_device *hw_dev, bool state)
Simon Wilson19957a32012-04-06 16:17:12 -07001349{
Paul McLean76dba682016-06-01 12:29:11 -06001350 struct audio_device * adev = (struct audio_device *)hw_dev;
Paul McLean994ac072016-06-02 15:33:24 -06001351 device_lock(adev);
Eric Laurent253def92014-09-14 12:18:18 -07001352 adev->mic_muted = state;
Paul McLean994ac072016-06-02 15:33:24 -06001353 device_unlock(adev);
Simon Wilson19957a32012-04-06 16:17:12 -07001354 return -ENOSYS;
1355}
1356
Paul McLean76dba682016-06-01 12:29:11 -06001357static int adev_get_mic_mute(const struct audio_hw_device *hw_dev, bool *state)
Simon Wilson19957a32012-04-06 16:17:12 -07001358{
1359 return -ENOSYS;
1360}
1361
Paul McLean76dba682016-06-01 12:29:11 -06001362static int adev_dump(const struct audio_hw_device *device, int fd)
Simon Wilson19957a32012-04-06 16:17:12 -07001363{
Paul McLean6a75e4e2016-05-25 14:09:02 -06001364 dprintf(fd, "\nUSB audio module:\n");
1365
1366 struct audio_device* adev = (struct audio_device*)device;
1367 const int kNumRetries = 3;
1368 const int kSleepTimeMS = 500;
1369
Paul McLean994ac072016-06-02 15:33:24 -06001370 // use device_try_lock() in case we dumpsys during a deadlock
Paul McLean6a75e4e2016-05-25 14:09:02 -06001371 int retry = kNumRetries;
Paul McLean994ac072016-06-02 15:33:24 -06001372 while (retry > 0 && device_try_lock(adev) != 0) {
Paul McLean6a75e4e2016-05-25 14:09:02 -06001373 sleep(kSleepTimeMS);
1374 retry--;
1375 }
1376
1377 if (retry > 0) {
1378 if (list_empty(&adev->output_stream_list)) {
1379 dprintf(fd, " No output streams.\n");
1380 } else {
1381 struct listnode* node;
1382 list_for_each(node, &adev->output_stream_list) {
1383 struct audio_stream* stream =
1384 (struct audio_stream *)node_to_item(node, struct stream_out, list_node);
1385 out_dump(stream, fd);
1386 }
1387 }
1388
1389 if (list_empty(&adev->input_stream_list)) {
1390 dprintf(fd, "\n No input streams.\n");
1391 } else {
1392 struct listnode* node;
1393 list_for_each(node, &adev->input_stream_list) {
1394 struct audio_stream* stream =
1395 (struct audio_stream *)node_to_item(node, struct stream_in, list_node);
1396 in_dump(stream, fd);
1397 }
1398 }
1399
Paul McLean994ac072016-06-02 15:33:24 -06001400 device_unlock(adev);
Paul McLean6a75e4e2016-05-25 14:09:02 -06001401 } else {
1402 // Couldn't lock
1403 dprintf(fd, " Could not obtain device lock.\n");
1404 }
1405
Simon Wilson19957a32012-04-06 16:17:12 -07001406 return 0;
1407}
1408
1409static int adev_close(hw_device_t *device)
1410{
Simon Wilson19957a32012-04-06 16:17:12 -07001411 free(device);
Paul McLeaneedc92e2013-12-19 15:46:15 -08001412
Simon Wilson19957a32012-04-06 16:17:12 -07001413 return 0;
1414}
1415
Paul McLean30f41852014-04-16 15:44:20 -07001416static int adev_open(const hw_module_t* module, const char* name, hw_device_t** device)
Simon Wilson19957a32012-04-06 16:17:12 -07001417{
Simon Wilson19957a32012-04-06 16:17:12 -07001418 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
1419 return -EINVAL;
1420
Paul McLeaneedc92e2013-12-19 15:46:15 -08001421 struct audio_device *adev = calloc(1, sizeof(struct audio_device));
Simon Wilson19957a32012-04-06 16:17:12 -07001422 if (!adev)
1423 return -ENOMEM;
1424
Paul McLeancf5310a2018-08-22 14:33:12 -07001425 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
Paul McLeanc88e6ae2014-07-16 09:48:34 -07001426
Paul McLean6a75e4e2016-05-25 14:09:02 -06001427 list_init(&adev->output_stream_list);
1428 list_init(&adev->input_stream_list);
1429
Simon Wilson19957a32012-04-06 16:17:12 -07001430 adev->hw_device.common.tag = HARDWARE_DEVICE_TAG;
Eric Laurent85e08e22012-08-28 14:30:35 -07001431 adev->hw_device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
Paul McLeanc88e6ae2014-07-16 09:48:34 -07001432 adev->hw_device.common.module = (struct hw_module_t *)module;
Simon Wilson19957a32012-04-06 16:17:12 -07001433 adev->hw_device.common.close = adev_close;
1434
Simon Wilson19957a32012-04-06 16:17:12 -07001435 adev->hw_device.init_check = adev_init_check;
1436 adev->hw_device.set_voice_volume = adev_set_voice_volume;
1437 adev->hw_device.set_master_volume = adev_set_master_volume;
1438 adev->hw_device.set_mode = adev_set_mode;
1439 adev->hw_device.set_mic_mute = adev_set_mic_mute;
1440 adev->hw_device.get_mic_mute = adev_get_mic_mute;
1441 adev->hw_device.set_parameters = adev_set_parameters;
1442 adev->hw_device.get_parameters = adev_get_parameters;
1443 adev->hw_device.get_input_buffer_size = adev_get_input_buffer_size;
1444 adev->hw_device.open_output_stream = adev_open_output_stream;
1445 adev->hw_device.close_output_stream = adev_close_output_stream;
1446 adev->hw_device.open_input_stream = adev_open_input_stream;
1447 adev->hw_device.close_input_stream = adev_close_input_stream;
1448 adev->hw_device.dump = adev_dump;
1449
1450 *device = &adev->hw_device.common;
1451
1452 return 0;
1453}
1454
1455static struct hw_module_methods_t hal_module_methods = {
1456 .open = adev_open,
1457};
1458
1459struct audio_module HAL_MODULE_INFO_SYM = {
1460 .common = {
1461 .tag = HARDWARE_MODULE_TAG,
Mike Lockwood46a98092012-04-24 16:41:18 -07001462 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
1463 .hal_api_version = HARDWARE_HAL_API_VERSION,
Simon Wilson19957a32012-04-06 16:17:12 -07001464 .id = AUDIO_HARDWARE_MODULE_ID,
1465 .name = "USB audio HW HAL",
1466 .author = "The Android Open Source Project",
1467 .methods = &hal_module_methods,
1468 },
1469};