blob: 7c16ad1ef884fa04cb436e66839ba2f38632d084 [file] [log] [blame]
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -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
17#define LOG_TAG "r_submix"
Jean-Michel Trivi35a2c162012-09-17 10:13:26 -070018//#define LOG_NDEBUG 0
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -070019
20#include <errno.h>
21#include <pthread.h>
22#include <stdint.h>
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -070023#include <stdlib.h>
Stewart Milesc049a0a2014-05-01 09:03:27 -070024#include <sys/param.h>
25#include <sys/time.h>
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -070026
27#include <cutils/log.h>
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -070028#include <cutils/properties.h>
Stewart Milesc049a0a2014-05-01 09:03:27 -070029#include <cutils/str_parms.h>
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -070030
Stewart Milesc049a0a2014-05-01 09:03:27 -070031#include <hardware/audio.h>
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -070032#include <hardware/hardware.h>
33#include <system/audio.h>
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -070034
Stewart Milesc049a0a2014-05-01 09:03:27 -070035#include <media/AudioParameter.h>
36#include <media/AudioBufferProvider.h>
Jean-Michel Trivieec87702012-09-17 09:59:42 -070037#include <media/nbaio/MonoPipe.h>
38#include <media/nbaio/MonoPipeReader.h>
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -070039
Jean-Michel Trivid4413032012-09-30 11:08:06 -070040#include <utils/String8.h>
Jean-Michel Trivid4413032012-09-30 11:08:06 -070041
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -070042extern "C" {
43
44namespace android {
45
Stewart Milesc049a0a2014-05-01 09:03:27 -070046// Set to 1 to enable extremely verbose logging in this module.
47#define SUBMIX_VERBOSE_LOGGING 0
48#if SUBMIX_VERBOSE_LOGGING
49#define SUBMIX_ALOGV(...) ALOGV(__VA_ARGS__)
50#define SUBMIX_ALOGE(...) ALOGE(__VA_ARGS__)
51#else
52#define SUBMIX_ALOGV(...)
53#define SUBMIX_ALOGE(...)
54#endif // SUBMIX_VERBOSE_LOGGING
55
Stewart Miles3dd36f92014-05-01 09:03:27 -070056// NOTE: This value will be rounded up to the nearest power of 2 by MonoPipe().
57#define DEFAULT_PIPE_SIZE_IN_FRAMES (1024*8)
58// Value used to divide the MonoPipe() buffer into segments that are written to the source and
59// read from the sink. The maximum latency of the device is the size of the MonoPipe's buffer
60// the minimum latency is the MonoPipe buffer size divided by this value.
61#define DEFAULT_PIPE_PERIOD_COUNT 4
Jean-Michel Trivieec87702012-09-17 09:59:42 -070062// The duration of MAX_READ_ATTEMPTS * READ_ATTEMPT_SLEEP_MS must be stricly inferior to
63// the duration of a record buffer at the current record sample rate (of the device, not of
64// the recording itself). Here we have:
65// 3 * 5ms = 15ms < 1024 frames * 1000 / 48000 = 21.333ms
Jean-Michel Trivi6acd9662012-09-11 19:19:08 -070066#define MAX_READ_ATTEMPTS 3
Jean-Michel Trivieec87702012-09-17 09:59:42 -070067#define READ_ATTEMPT_SLEEP_MS 5 // 5ms between two read attempts when pipe is empty
Stewart Miles568e66f2014-05-01 09:03:27 -070068#define DEFAULT_SAMPLE_RATE_HZ 48000 // default sample rate
69// See NBAIO_Format frameworks/av/include/media/nbaio/NBAIO.h.
70#define DEFAULT_FORMAT AUDIO_FORMAT_PCM_16_BIT
Stewart Miles3dd36f92014-05-01 09:03:27 -070071// A legacy user of this device does not close the input stream when it shuts down, which
72// results in the application opening a new input stream before closing the old input stream
73// handle it was previously using. Setting this value to 1 allows multiple clients to open
74// multiple input streams from this device. If this option is enabled, each input stream returned
75// is *the same stream* which means that readers will race to read data from these streams.
76#define ENABLE_LEGACY_INPUT_OPEN 1
77
78// Common limits macros.
79#ifndef min
80#define min(a, b) ((a) < (b) ? (a) : (b))
81#endif // min
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -070082
Stewart Miles70726842014-05-01 09:03:27 -070083// Set *result_variable_ptr to true if value_to_find is present in the array array_to_search,
84// otherwise set *result_variable_ptr to false.
85#define SUBMIX_VALUE_IN_SET(value_to_find, array_to_search, result_variable_ptr) \
86 { \
87 size_t i; \
88 *(result_variable_ptr) = false; \
89 for (i = 0; i < sizeof(array_to_search) / sizeof((array_to_search)[0]); i++) { \
90 if ((value_to_find) == (array_to_search)[i]) { \
91 *(result_variable_ptr) = true; \
92 break; \
93 } \
94 } \
95 }
96
Stewart Miles568e66f2014-05-01 09:03:27 -070097// Configuration of the submix pipe.
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -070098struct submix_config {
Stewart Miles70726842014-05-01 09:03:27 -070099 // Channel mask field in this data structure is set to either input_channel_mask or
100 // output_channel_mask depending upon the last stream to be opened on this device.
101 struct audio_config common;
102 // Input stream and output stream channel masks. This is required since input and output
103 // channel bitfields are not equivalent.
104 audio_channel_mask_t input_channel_mask;
105 audio_channel_mask_t output_channel_mask;
Stewart Miles3dd36f92014-05-01 09:03:27 -0700106 size_t buffer_size_frames; // Size of the audio pipe in frames.
107 // Maximum number of frames buffered by the input and output streams.
108 size_t buffer_period_size_frames;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700109};
110
111struct submix_audio_device {
112 struct audio_hw_device device;
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700113 bool input_standby;
Stewart Miles70726842014-05-01 09:03:27 -0700114 bool output_standby;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700115 submix_config config;
116 // Pipe variables: they handle the ring buffer that "pipes" audio:
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700117 // - from the submix virtual audio output == what needs to be played
118 // remotely, seen as an output for AudioFlinger
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700119 // - to the virtual audio source == what is captured by the component
120 // which "records" the submix / virtual audio source, and handles it as needed.
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700121 // A usecase example is one where the component capturing the audio is then sending it over
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700122 // Wifi for presentation on a remote Wifi Display device (e.g. a dongle attached to a TV, or a
123 // TV with Wifi Display capabilities), or to a wireless audio player.
Stewart Miles568e66f2014-05-01 09:03:27 -0700124 sp<MonoPipe> rsxSink;
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700125 sp<MonoPipeReader> rsxSource;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700126
Stewart Miles3dd36f92014-05-01 09:03:27 -0700127 // Pointers to the current input and output stream instances. rsxSink and rsxSource are
128 // destroyed if both and input and output streams are destroyed.
129 struct submix_stream_out *output;
130 struct submix_stream_in *input;
131
Stewart Miles568e66f2014-05-01 09:03:27 -0700132 // Device lock, also used to protect access to submix_audio_device from the input and output
133 // streams.
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700134 pthread_mutex_t lock;
135};
136
137struct submix_stream_out {
138 struct audio_stream_out stream;
139 struct submix_audio_device *dev;
140};
141
142struct submix_stream_in {
143 struct audio_stream_in stream;
144 struct submix_audio_device *dev;
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700145 bool output_standby; // output standby state as seen from record thread
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700146
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700147 // wall clock when recording starts
148 struct timespec record_start_time;
149 // how many frames have been requested to be read
150 int64_t read_counter_frames;
Stewart Miles3dd36f92014-05-01 09:03:27 -0700151
152#if ENABLE_LEGACY_INPUT_OPEN
153 // Number of references to this input stream.
154 volatile int32_t ref_count;
155#endif // ENABLE_LEGACY_INPUT_OPEN
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700156};
Jean-Michel Trivi6acd9662012-09-11 19:19:08 -0700157
Stewart Miles70726842014-05-01 09:03:27 -0700158// Determine whether the specified sample rate is supported by the submix module.
159static bool sample_rate_supported(const uint32_t sample_rate)
160{
161 // Set of sample rates supported by Format_from_SR_C() frameworks/av/media/libnbaio/NAIO.cpp.
162 static const unsigned int supported_sample_rates[] = {
163 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000,
164 };
165 bool return_value;
166 SUBMIX_VALUE_IN_SET(sample_rate, supported_sample_rates, &return_value);
167 return return_value;
168}
169
170// Determine whether the specified sample rate is supported, if it is return the specified sample
171// rate, otherwise return the default sample rate for the submix module.
172static uint32_t get_supported_sample_rate(uint32_t sample_rate)
173{
174 return sample_rate_supported(sample_rate) ? sample_rate : DEFAULT_SAMPLE_RATE_HZ;
175}
176
177// Determine whether the specified channel in mask is supported by the submix module.
178static bool channel_in_mask_supported(const audio_channel_mask_t channel_in_mask)
179{
180 // Set of channel in masks supported by Format_from_SR_C()
181 // frameworks/av/media/libnbaio/NAIO.cpp.
182 static const audio_channel_mask_t supported_channel_in_masks[] = {
183 AUDIO_CHANNEL_IN_MONO, AUDIO_CHANNEL_IN_STEREO,
184 };
185 bool return_value;
186 SUBMIX_VALUE_IN_SET(channel_in_mask, supported_channel_in_masks, &return_value);
187 return return_value;
188}
189
190// Determine whether the specified channel in mask is supported, if it is return the specified
191// channel in mask, otherwise return the default channel in mask for the submix module.
192static audio_channel_mask_t get_supported_channel_in_mask(
193 const audio_channel_mask_t channel_in_mask)
194{
195 return channel_in_mask_supported(channel_in_mask) ? channel_in_mask :
196 static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_IN_STEREO);
197}
198
199// Determine whether the specified channel out mask is supported by the submix module.
200static bool channel_out_mask_supported(const audio_channel_mask_t channel_out_mask)
201{
202 // Set of channel out masks supported by Format_from_SR_C()
203 // frameworks/av/media/libnbaio/NAIO.cpp.
204 static const audio_channel_mask_t supported_channel_out_masks[] = {
205 AUDIO_CHANNEL_OUT_MONO, AUDIO_CHANNEL_OUT_STEREO,
206 };
207 bool return_value;
208 SUBMIX_VALUE_IN_SET(channel_out_mask, supported_channel_out_masks, &return_value);
209 return return_value;
210}
211
212// Determine whether the specified channel out mask is supported, if it is return the specified
213// channel out mask, otherwise return the default channel out mask for the submix module.
214static audio_channel_mask_t get_supported_channel_out_mask(
215 const audio_channel_mask_t channel_out_mask)
216{
217 return channel_out_mask_supported(channel_out_mask) ? channel_out_mask :
218 static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_OUT_STEREO);
219}
220
Stewart Milesf645c5e2014-05-01 09:03:27 -0700221// Get a pointer to submix_stream_out given an audio_stream_out that is embedded within the
222// structure.
223static struct submix_stream_out * audio_stream_out_get_submix_stream_out(
224 struct audio_stream_out * const stream)
225{
226 ALOG_ASSERT(stream);
227 return reinterpret_cast<struct submix_stream_out *>(reinterpret_cast<uint8_t *>(stream) -
228 offsetof(struct submix_stream_out, stream));
229}
230
231// Get a pointer to submix_stream_out given an audio_stream that is embedded within the structure.
232static struct submix_stream_out * audio_stream_get_submix_stream_out(
233 struct audio_stream * const stream)
234{
235 ALOG_ASSERT(stream);
236 return audio_stream_out_get_submix_stream_out(
237 reinterpret_cast<struct audio_stream_out *>(stream));
238}
239
240// Get a pointer to submix_stream_in given an audio_stream_in that is embedded within the
241// structure.
242static struct submix_stream_in * audio_stream_in_get_submix_stream_in(
243 struct audio_stream_in * const stream)
244{
245 ALOG_ASSERT(stream);
246 return reinterpret_cast<struct submix_stream_in *>(reinterpret_cast<uint8_t *>(stream) -
247 offsetof(struct submix_stream_in, stream));
248}
249
250// Get a pointer to submix_stream_in given an audio_stream that is embedded within the structure.
251static struct submix_stream_in * audio_stream_get_submix_stream_in(
252 struct audio_stream * const stream)
253{
254 ALOG_ASSERT(stream);
255 return audio_stream_in_get_submix_stream_in(
256 reinterpret_cast<struct audio_stream_in *>(stream));
257}
258
259// Get a pointer to submix_audio_device given a pointer to an audio_device that is embedded within
260// the structure.
261static struct submix_audio_device * audio_hw_device_get_submix_audio_device(
262 struct audio_hw_device *device)
263{
264 ALOG_ASSERT(device);
265 return reinterpret_cast<struct submix_audio_device *>(reinterpret_cast<uint8_t *>(device) -
266 offsetof(struct submix_audio_device, device));
267}
268
Stewart Miles568e66f2014-05-01 09:03:27 -0700269// Get the number of channels referenced by the specified channel_mask. The channel_mask can
270// reference either input or output channels.
271uint32_t get_channel_count_from_mask(const audio_channel_mask_t channel_mask) {
272 if (audio_is_input_channel(channel_mask)) {
273 return popcount(channel_mask & AUDIO_CHANNEL_IN_ALL);
274 } else if (audio_is_output_channel(channel_mask)) {
275 return popcount(channel_mask & AUDIO_CHANNEL_OUT_ALL);
276 }
277 ALOGE("get_channel_count(): No channels specified in channel mask %x", channel_mask);
278 return 0;
279}
280
Stewart Miles70726842014-05-01 09:03:27 -0700281// Compare an audio_config with input channel mask and an audio_config with output channel mask
282// returning false if they do *not* match, true otherwise.
283static bool audio_config_compare(const audio_config * const input_config,
284 const audio_config * const output_config)
285{
Stewart Miles3dd36f92014-05-01 09:03:27 -0700286 const uint32_t input_channels = get_channel_count_from_mask(input_config->channel_mask);
287 const uint32_t output_channels = get_channel_count_from_mask(output_config->channel_mask);
288 if (input_channels != output_channels) {
289 ALOGE("audio_config_compare() channel count mismatch input=%d vs. output=%d",
290 input_channels, output_channels);
Stewart Miles70726842014-05-01 09:03:27 -0700291 return false;
292 }
293 if (input_config->sample_rate != output_config->sample_rate) {
294 ALOGE("audio_config_compare() sample rate mismatch %ul vs. %ul",
295 input_config->sample_rate, output_config->sample_rate);
296 return false;
297 }
298 if (input_config->format != output_config->format) {
299 ALOGE("audio_config_compare() format mismatch %x vs. %x",
300 input_config->format, output_config->format);
301 return false;
302 }
303 // This purposely ignores offload_info as it's not required for the submix device.
304 return true;
305}
306
Stewart Miles3dd36f92014-05-01 09:03:27 -0700307// If one doesn't exist, create a pipe for the submix audio device rsxadev of size
308// buffer_size_frames and optionally associate "in" or "out" with the submix audio device.
309static void submix_audio_device_create_pipe(struct submix_audio_device * const rsxadev,
310 const struct audio_config * const config,
311 const size_t buffer_size_frames,
312 const uint32_t buffer_period_count,
313 struct submix_stream_in * const in,
314 struct submix_stream_out * const out)
315{
316 ALOG_ASSERT(in || out);
317 ALOGV("submix_audio_device_create_pipe()");
318 pthread_mutex_lock(&rsxadev->lock);
319 // Save a reference to the specified input or output stream and the associated channel
320 // mask.
321 if (in) {
322 rsxadev->input = in;
323 rsxadev->config.input_channel_mask = config->channel_mask;
324 }
325 if (out) {
326 rsxadev->output = out;
327 rsxadev->config.output_channel_mask = config->channel_mask;
328 }
329 // If a pipe isn't associated with the device, create one.
330 if (rsxadev->rsxSink == NULL || rsxadev->rsxSource == NULL) {
331 struct submix_config * const device_config = &rsxadev->config;
332 const NBAIO_Format format = Format_from_SR_C(config->sample_rate,
333 get_channel_count_from_mask(config->channel_mask), config->format);
334 const NBAIO_Format offers[1] = {format};
335 size_t numCounterOffers = 0;
336 // Create a MonoPipe with optional blocking set to true.
337 MonoPipe* sink = new MonoPipe(buffer_size_frames, format, true /*writeCanBlock*/);
338 // Negotiation between the source and sink cannot fail as the device open operation
339 // creates both ends of the pipe using the same audio format.
340 ssize_t index = sink->negotiate(offers, 1, NULL, numCounterOffers);
341 ALOG_ASSERT(index == 0);
342 MonoPipeReader* source = new MonoPipeReader(sink);
343 numCounterOffers = 0;
344 index = source->negotiate(offers, 1, NULL, numCounterOffers);
345 ALOG_ASSERT(index == 0);
346 ALOGV("submix_audio_device_create_pipe(): created pipe");
347
348 // Save references to the source and sink.
349 ALOG_ASSERT(rsxadev->rsxSink == NULL);
350 ALOG_ASSERT(rsxadev->rsxSource == NULL);
351 rsxadev->rsxSink = sink;
352 rsxadev->rsxSource = source;
353 // Store the sanitized audio format in the device so that it's possible to determine
354 // the format of the pipe source when opening the input device.
355 memcpy(&device_config->common, config, sizeof(device_config->common));
356 device_config->buffer_size_frames = sink->maxFrames();
357 device_config->buffer_period_size_frames = device_config->buffer_size_frames /
358 buffer_period_count;
359 }
360 pthread_mutex_unlock(&rsxadev->lock);
361}
362
363// Release references to the sink and source. Input and output threads may maintain references
364// to these objects via StrongPointer (sp<MonoPipe> and sp<MonoPipeReader>) which they can use
365// before they shutdown.
366static void submix_audio_device_release_pipe(struct submix_audio_device * const rsxadev)
367{
368 ALOGV("submix_audio_device_release_pipe()");
369 rsxadev->rsxSink.clear();
370 rsxadev->rsxSource.clear();
371}
372
373// Remove references to the specified input and output streams. When the device no longer
374// references input and output streams destroy the associated pipe.
375static void submix_audio_device_destroy_pipe(struct submix_audio_device * const rsxadev,
376 const struct submix_stream_in * const in,
377 const struct submix_stream_out * const out)
378{
379 MonoPipe* sink;
380 pthread_mutex_lock(&rsxadev->lock);
381 ALOGV("submix_audio_device_destroy_pipe()");
382 ALOG_ASSERT(in == NULL || rsxadev->input == in);
383 ALOG_ASSERT(out == NULL || rsxadev->output == out);
384 if (in != NULL) {
385#if ENABLE_LEGACY_INPUT_OPEN
386 const_cast<struct submix_stream_in*>(in)->ref_count--;
387 if (in->ref_count == 0) {
388 rsxadev->input = NULL;
389 }
390 ALOGV("submix_audio_device_destroy_pipe(): input ref_count %d", in->ref_count);
391#else
392 rsxadev->input = NULL;
393#endif // ENABLE_LEGACY_INPUT_OPEN
394 }
395 if (out != NULL) rsxadev->output = NULL;
396 if (rsxadev->input != NULL && rsxadev->output != NULL) {
397 submix_audio_device_release_pipe(rsxadev);
398 ALOGV("submix_audio_device_destroy_pipe(): pipe destroyed");
399 }
400 pthread_mutex_unlock(&rsxadev->lock);
401}
402
Stewart Miles70726842014-05-01 09:03:27 -0700403// Sanitize the user specified audio config for a submix input / output stream.
404static void submix_sanitize_config(struct audio_config * const config, const bool is_input_format)
405{
406 config->channel_mask = is_input_format ? get_supported_channel_in_mask(config->channel_mask) :
407 get_supported_channel_out_mask(config->channel_mask);
408 config->sample_rate = get_supported_sample_rate(config->sample_rate);
409 config->format = DEFAULT_FORMAT;
410}
411
412// Verify a submix input or output stream can be opened.
413static bool submix_open_validate(const struct submix_audio_device * const rsxadev,
414 pthread_mutex_t * const lock,
415 const struct audio_config * const config,
416 const bool opening_input)
417{
Stewart Miles3dd36f92014-05-01 09:03:27 -0700418 bool input_open;
419 bool output_open;
Stewart Miles70726842014-05-01 09:03:27 -0700420 audio_config pipe_config;
421
422 // Query the device for the current audio config and whether input and output streams are open.
423 pthread_mutex_lock(lock);
Stewart Miles3dd36f92014-05-01 09:03:27 -0700424 output_open = rsxadev->output != NULL;
425 input_open = rsxadev->input != NULL;
Stewart Miles70726842014-05-01 09:03:27 -0700426 memcpy(&pipe_config, &rsxadev->config.common, sizeof(pipe_config));
427 pthread_mutex_unlock(lock);
428
Stewart Miles3dd36f92014-05-01 09:03:27 -0700429 // If the stream is already open, don't open it again.
430 if (opening_input ? !ENABLE_LEGACY_INPUT_OPEN && input_open : output_open) {
431 ALOGE("submix_open_validate(): %s stream already open.", opening_input ? "Input" :
432 "Output");
433 return false;
434 }
435
436 SUBMIX_ALOGV("submix_open_validate(): sample rate=%d format=%x "
437 "%s_channel_mask=%x", config->sample_rate, config->format,
438 opening_input ? "in" : "out", config->channel_mask);
439
440 // If either stream is open, verify the existing audio config the pipe matches the user
Stewart Miles70726842014-05-01 09:03:27 -0700441 // specified config.
Stewart Miles3dd36f92014-05-01 09:03:27 -0700442 if (input_open || output_open) {
Stewart Miles70726842014-05-01 09:03:27 -0700443 const audio_config * const input_config = opening_input ? config : &pipe_config;
444 const audio_config * const output_config = opening_input ? &pipe_config : config;
445 // Get the channel mask of the open device.
446 pipe_config.channel_mask =
447 opening_input ? rsxadev->config.output_channel_mask :
448 rsxadev->config.input_channel_mask;
449 if (!audio_config_compare(input_config, output_config)) {
450 ALOGE("submix_open_validate(): Unsupported format.");
Stewart Miles3dd36f92014-05-01 09:03:27 -0700451 return false;
Stewart Miles70726842014-05-01 09:03:27 -0700452 }
453 }
454 return true;
455}
456
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700457/* audio HAL functions */
458
459static uint32_t out_get_sample_rate(const struct audio_stream *stream)
460{
Stewart Milesf645c5e2014-05-01 09:03:27 -0700461 const struct submix_stream_out * const out = audio_stream_get_submix_stream_out(
462 const_cast<struct audio_stream *>(stream));
Stewart Miles70726842014-05-01 09:03:27 -0700463 const uint32_t out_rate = out->dev->config.common.sample_rate;
Stewart Milesc049a0a2014-05-01 09:03:27 -0700464 SUBMIX_ALOGV("out_get_sample_rate() returns %u", out_rate);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700465 return out_rate;
466}
467
468static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
469{
Stewart Miles70726842014-05-01 09:03:27 -0700470 if (!sample_rate_supported(rate)) {
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700471 ALOGE("out_set_sample_rate(rate=%u) rate unsupported", rate);
472 return -ENOSYS;
473 }
Stewart Milesf645c5e2014-05-01 09:03:27 -0700474 struct submix_stream_out * const out = audio_stream_get_submix_stream_out(stream);
Stewart Milesc049a0a2014-05-01 09:03:27 -0700475 SUBMIX_ALOGV("out_set_sample_rate(rate=%u)", rate);
Stewart Miles70726842014-05-01 09:03:27 -0700476 out->dev->config.common.sample_rate = rate;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700477 return 0;
478}
479
480static size_t out_get_buffer_size(const struct audio_stream *stream)
481{
Stewart Milesf645c5e2014-05-01 09:03:27 -0700482 const struct submix_stream_out * const out = audio_stream_get_submix_stream_out(
483 const_cast<struct audio_stream *>(stream));
Stewart Miles568e66f2014-05-01 09:03:27 -0700484 const struct submix_config * const config = &out->dev->config;
Stewart Miles3dd36f92014-05-01 09:03:27 -0700485 const size_t buffer_size = config->buffer_period_size_frames * audio_stream_frame_size(stream);
Stewart Miles568e66f2014-05-01 09:03:27 -0700486 SUBMIX_ALOGV("out_get_buffer_size() returns %zu bytes, %zu frames",
Stewart Miles3dd36f92014-05-01 09:03:27 -0700487 buffer_size, config->buffer_period_size_frames);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700488 return buffer_size;
489}
490
491static audio_channel_mask_t out_get_channels(const struct audio_stream *stream)
492{
Stewart Milesf645c5e2014-05-01 09:03:27 -0700493 const struct submix_stream_out * const out = audio_stream_get_submix_stream_out(
494 const_cast<struct audio_stream *>(stream));
Stewart Miles70726842014-05-01 09:03:27 -0700495 uint32_t channel_mask = out->dev->config.output_channel_mask;
Stewart Miles568e66f2014-05-01 09:03:27 -0700496 SUBMIX_ALOGV("out_get_channels() returns %08x", channel_mask);
497 return channel_mask;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700498}
499
500static audio_format_t out_get_format(const struct audio_stream *stream)
501{
Stewart Miles568e66f2014-05-01 09:03:27 -0700502 const struct submix_stream_out * const out = audio_stream_get_submix_stream_out(
503 const_cast<struct audio_stream *>(stream));
Stewart Miles70726842014-05-01 09:03:27 -0700504 const audio_format_t format = out->dev->config.common.format;
Stewart Miles568e66f2014-05-01 09:03:27 -0700505 SUBMIX_ALOGV("out_get_format() returns %x", format);
506 return format;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700507}
508
509static int out_set_format(struct audio_stream *stream, audio_format_t format)
510{
Stewart Miles568e66f2014-05-01 09:03:27 -0700511 const struct submix_stream_out * const out = audio_stream_get_submix_stream_out(stream);
Stewart Miles70726842014-05-01 09:03:27 -0700512 if (format != out->dev->config.common.format) {
Stewart Milesc049a0a2014-05-01 09:03:27 -0700513 ALOGE("out_set_format(format=%x) format unsupported", format);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700514 return -ENOSYS;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700515 }
Stewart Milesc049a0a2014-05-01 09:03:27 -0700516 SUBMIX_ALOGV("out_set_format(format=%x)", format);
517 return 0;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700518}
519
520static int out_standby(struct audio_stream *stream)
521{
Stewart Milesf645c5e2014-05-01 09:03:27 -0700522 struct submix_audio_device * const rsxadev = audio_stream_get_submix_stream_out(stream)->dev;
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700523 ALOGI("out_standby()");
524
Stewart Milesf645c5e2014-05-01 09:03:27 -0700525 pthread_mutex_lock(&rsxadev->lock);
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700526
Stewart Milesf645c5e2014-05-01 09:03:27 -0700527 rsxadev->output_standby = true;
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700528
Stewart Milesf645c5e2014-05-01 09:03:27 -0700529 pthread_mutex_unlock(&rsxadev->lock);
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700530
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700531 return 0;
532}
533
534static int out_dump(const struct audio_stream *stream, int fd)
535{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700536 (void)stream;
537 (void)fd;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700538 return 0;
539}
540
541static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
542{
Jean-Michel Trivid4413032012-09-30 11:08:06 -0700543 int exiting = -1;
544 AudioParameter parms = AudioParameter(String8(kvpairs));
Stewart Milesc049a0a2014-05-01 09:03:27 -0700545 SUBMIX_ALOGV("out_set_parameters() kvpairs='%s'", kvpairs);
Stewart Miles3dd36f92014-05-01 09:03:27 -0700546
Jean-Michel Trivid4413032012-09-30 11:08:06 -0700547 // FIXME this is using hard-coded strings but in the future, this functionality will be
548 // converted to use audio HAL extensions required to support tunneling
549 if ((parms.getInt(String8("exiting"), exiting) == NO_ERROR) && (exiting > 0)) {
Stewart Milesf645c5e2014-05-01 09:03:27 -0700550 struct submix_audio_device * const rsxadev =
551 audio_stream_get_submix_stream_out(stream)->dev;
552 pthread_mutex_lock(&rsxadev->lock);
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800553 { // using the sink
Stewart Miles3dd36f92014-05-01 09:03:27 -0700554 sp<MonoPipe> sink = rsxadev->rsxSink;
Stewart Milesf645c5e2014-05-01 09:03:27 -0700555 if (sink == NULL) {
556 pthread_mutex_unlock(&rsxadev->lock);
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800557 return 0;
558 }
Jean-Michel Trivid4413032012-09-30 11:08:06 -0700559
Stewart Milesc049a0a2014-05-01 09:03:27 -0700560 ALOGI("out_set_parameters(): shutdown");
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800561 sink->shutdown(true);
562 } // done using the sink
Stewart Milesf645c5e2014-05-01 09:03:27 -0700563 pthread_mutex_unlock(&rsxadev->lock);
Jean-Michel Trivid4413032012-09-30 11:08:06 -0700564 }
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700565 return 0;
566}
567
568static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
569{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700570 (void)stream;
571 (void)keys;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700572 return strdup("");
573}
574
575static uint32_t out_get_latency(const struct audio_stream_out *stream)
576{
Stewart Milesf645c5e2014-05-01 09:03:27 -0700577 const struct submix_stream_out * const out = audio_stream_out_get_submix_stream_out(
578 const_cast<struct audio_stream_out *>(stream));
Stewart Miles568e66f2014-05-01 09:03:27 -0700579 const struct submix_config * const config = &out->dev->config;
Stewart Miles3dd36f92014-05-01 09:03:27 -0700580 const uint32_t latency_ms = (config->buffer_size_frames * 1000) / config->common.sample_rate;
Stewart Miles568e66f2014-05-01 09:03:27 -0700581 SUBMIX_ALOGV("out_get_latency() returns %u ms, size in frames %zu, sample rate %u", latency_ms,
Stewart Miles3dd36f92014-05-01 09:03:27 -0700582 config->buffer_size_frames, config->common.sample_rate);
Stewart Miles568e66f2014-05-01 09:03:27 -0700583 return latency_ms;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700584}
585
586static int out_set_volume(struct audio_stream_out *stream, float left,
587 float right)
588{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700589 (void)stream;
590 (void)left;
591 (void)right;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700592 return -ENOSYS;
593}
594
595static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
596 size_t bytes)
597{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700598 SUBMIX_ALOGV("out_write(bytes=%zd)", bytes);
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700599 ssize_t written_frames = 0;
Jean-Michel Trivi90b0fbd2012-10-30 19:03:22 -0700600 const size_t frame_size = audio_stream_frame_size(&stream->common);
Stewart Miles3dd36f92014-05-01 09:03:27 -0700601 struct submix_stream_out * const out = audio_stream_out_get_submix_stream_out(stream);
602 struct submix_audio_device * const rsxadev = out->dev;
Jean-Michel Trivi90b0fbd2012-10-30 19:03:22 -0700603 const size_t frames = bytes / frame_size;
604
Stewart Milesf645c5e2014-05-01 09:03:27 -0700605 pthread_mutex_lock(&rsxadev->lock);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700606
Stewart Milesf645c5e2014-05-01 09:03:27 -0700607 rsxadev->output_standby = false;
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700608
Stewart Miles3dd36f92014-05-01 09:03:27 -0700609 sp<MonoPipe> sink = rsxadev->rsxSink;
Stewart Milesf645c5e2014-05-01 09:03:27 -0700610 if (sink != NULL) {
Jean-Michel Trivi90b0fbd2012-10-30 19:03:22 -0700611 if (sink->isShutdown()) {
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800612 sink.clear();
Stewart Milesf645c5e2014-05-01 09:03:27 -0700613 pthread_mutex_unlock(&rsxadev->lock);
Stewart Milesc049a0a2014-05-01 09:03:27 -0700614 SUBMIX_ALOGV("out_write(): pipe shutdown, ignoring the write.");
Jean-Michel Trivi90b0fbd2012-10-30 19:03:22 -0700615 // the pipe has already been shutdown, this buffer will be lost but we must
616 // simulate timing so we don't drain the output faster than realtime
617 usleep(frames * 1000000 / out_get_sample_rate(&stream->common));
618 return bytes;
619 }
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700620 } else {
Stewart Milesf645c5e2014-05-01 09:03:27 -0700621 pthread_mutex_unlock(&rsxadev->lock);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700622 ALOGE("out_write without a pipe!");
623 ALOG_ASSERT("out_write without a pipe!");
624 return 0;
625 }
626
Stewart Miles2d199fe2014-05-01 09:03:27 -0700627 // If the write to the sink would block when no input stream is present, flush enough frames
628 // from the pipe to make space to write the most recent data.
629 {
630 const size_t availableToWrite = sink->availableToWrite();
631 sp<MonoPipeReader> source = rsxadev->rsxSource;
632 if (rsxadev->input == NULL && availableToWrite < frames) {
633 static uint8_t flush_buffer[64];
634 const size_t flushBufferSizeFrames = sizeof(flush_buffer) / frame_size;
635 size_t frames_to_flush_from_source = frames - availableToWrite;
636 SUBMIX_ALOGV("out_write(): flushing %d frames from the pipe to avoid blocking",
637 frames_to_flush_from_source);
638 while (frames_to_flush_from_source) {
639 const size_t flush_size = min(frames_to_flush_from_source, flushBufferSizeFrames);
640 frames_to_flush_from_source -= flush_size;
641 source->read(flush_buffer, flush_size, AudioBufferProvider::kInvalidPTS);
642 }
643 }
644 }
645
Stewart Milesf645c5e2014-05-01 09:03:27 -0700646 pthread_mutex_unlock(&rsxadev->lock);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700647
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700648 written_frames = sink->write(buffer, frames);
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800649
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700650 if (written_frames < 0) {
651 if (written_frames == (ssize_t)NEGOTIATE) {
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700652 ALOGE("out_write() write to pipe returned NEGOTIATE");
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700653
Stewart Milesf645c5e2014-05-01 09:03:27 -0700654 pthread_mutex_lock(&rsxadev->lock);
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800655 sink.clear();
Stewart Milesf645c5e2014-05-01 09:03:27 -0700656 pthread_mutex_unlock(&rsxadev->lock);
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700657
658 written_frames = 0;
Jean-Michel Trivi6acd9662012-09-11 19:19:08 -0700659 return 0;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700660 } else {
661 // write() returned UNDERRUN or WOULD_BLOCK, retry
Colin Cross5685a082014-04-18 15:45:42 -0700662 ALOGE("out_write() write to pipe returned unexpected %zd", written_frames);
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700663 written_frames = sink->write(buffer, frames);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700664 }
665 }
666
Stewart Milesf645c5e2014-05-01 09:03:27 -0700667 pthread_mutex_lock(&rsxadev->lock);
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800668 sink.clear();
Stewart Milesf645c5e2014-05-01 09:03:27 -0700669 pthread_mutex_unlock(&rsxadev->lock);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700670
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700671 if (written_frames < 0) {
Colin Cross5685a082014-04-18 15:45:42 -0700672 ALOGE("out_write() failed writing to pipe with %zd", written_frames);
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700673 return 0;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700674 }
Stewart Milesc049a0a2014-05-01 09:03:27 -0700675 const ssize_t written_bytes = written_frames * frame_size;
676 SUBMIX_ALOGV("out_write() wrote %zd bytes %zd frames)", written_bytes, written_frames);
677 return written_bytes;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700678}
679
680static int out_get_render_position(const struct audio_stream_out *stream,
681 uint32_t *dsp_frames)
682{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700683 (void)stream;
684 (void)dsp_frames;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700685 return -EINVAL;
686}
687
688static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
689{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700690 (void)stream;
691 (void)effect;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700692 return 0;
693}
694
695static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
696{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700697 (void)stream;
698 (void)effect;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700699 return 0;
700}
701
702static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
703 int64_t *timestamp)
704{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700705 (void)stream;
706 (void)timestamp;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700707 return -EINVAL;
708}
709
710/** audio_stream_in implementation **/
711static uint32_t in_get_sample_rate(const struct audio_stream *stream)
712{
Stewart Milesf645c5e2014-05-01 09:03:27 -0700713 const struct submix_stream_in * const in = audio_stream_get_submix_stream_in(
714 const_cast<struct audio_stream*>(stream));
Stewart Miles70726842014-05-01 09:03:27 -0700715 SUBMIX_ALOGV("in_get_sample_rate() returns %u", in->dev->config.common.sample_rate);
716 return in->dev->config.common.sample_rate;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700717}
718
719static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
720{
Stewart Miles568e66f2014-05-01 09:03:27 -0700721 const struct submix_stream_in * const in = audio_stream_get_submix_stream_in(stream);
Stewart Miles70726842014-05-01 09:03:27 -0700722 if (!sample_rate_supported(rate)) {
723 ALOGE("in_set_sample_rate(rate=%u) rate unsupported", rate);
724 return -ENOSYS;
725 }
726 in->dev->config.common.sample_rate = rate;
Stewart Miles568e66f2014-05-01 09:03:27 -0700727 SUBMIX_ALOGV("in_set_sample_rate() set %u", rate);
728 return 0;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700729}
730
731static size_t in_get_buffer_size(const struct audio_stream *stream)
732{
Stewart Milesf645c5e2014-05-01 09:03:27 -0700733 const struct submix_stream_in * const in = audio_stream_get_submix_stream_in(
734 const_cast<struct audio_stream*>(stream));
Stewart Miles3dd36f92014-05-01 09:03:27 -0700735 const size_t buffer_size = in->dev->config.buffer_period_size_frames *
736 audio_stream_frame_size(stream);
Stewart Miles568e66f2014-05-01 09:03:27 -0700737 SUBMIX_ALOGV("in_get_buffer_size() returns %zu", buffer_size);
738 return buffer_size;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700739}
740
741static audio_channel_mask_t in_get_channels(const struct audio_stream *stream)
742{
Stewart Miles70726842014-05-01 09:03:27 -0700743 const struct submix_stream_in * const in = audio_stream_get_submix_stream_in(
744 const_cast<struct audio_stream*>(stream));
745 const audio_channel_mask_t channel_mask = in->dev->config.input_channel_mask;
746 SUBMIX_ALOGV("in_get_channels() returns %x", channel_mask);
747 return channel_mask;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700748}
749
750static audio_format_t in_get_format(const struct audio_stream *stream)
751{
Stewart Miles568e66f2014-05-01 09:03:27 -0700752 const struct submix_stream_in * const in = audio_stream_get_submix_stream_in(
Stewart Miles70726842014-05-01 09:03:27 -0700753 const_cast<struct audio_stream*>(stream));
754 const audio_format_t format = in->dev->config.common.format;
Stewart Miles568e66f2014-05-01 09:03:27 -0700755 SUBMIX_ALOGV("in_get_format() returns %x", format);
756 return format;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700757}
758
759static int in_set_format(struct audio_stream *stream, audio_format_t format)
760{
Stewart Miles568e66f2014-05-01 09:03:27 -0700761 const struct submix_stream_in * const in = audio_stream_get_submix_stream_in(stream);
Stewart Miles70726842014-05-01 09:03:27 -0700762 if (format != in->dev->config.common.format) {
Stewart Milesc049a0a2014-05-01 09:03:27 -0700763 ALOGE("in_set_format(format=%x) format unsupported", format);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700764 return -ENOSYS;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700765 }
Stewart Milesc049a0a2014-05-01 09:03:27 -0700766 SUBMIX_ALOGV("in_set_format(format=%x)", format);
767 return 0;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700768}
769
770static int in_standby(struct audio_stream *stream)
771{
Stewart Milesf645c5e2014-05-01 09:03:27 -0700772 struct submix_audio_device * const rsxadev = audio_stream_get_submix_stream_in(stream)->dev;
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700773 ALOGI("in_standby()");
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700774
Stewart Milesf645c5e2014-05-01 09:03:27 -0700775 pthread_mutex_lock(&rsxadev->lock);
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700776
Stewart Milesf645c5e2014-05-01 09:03:27 -0700777 rsxadev->input_standby = true;
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700778
Stewart Milesf645c5e2014-05-01 09:03:27 -0700779 pthread_mutex_unlock(&rsxadev->lock);
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700780
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700781 return 0;
782}
783
784static int in_dump(const struct audio_stream *stream, int fd)
785{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700786 (void)stream;
787 (void)fd;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700788 return 0;
789}
790
791static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
792{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700793 (void)stream;
794 (void)kvpairs;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700795 return 0;
796}
797
798static char * in_get_parameters(const struct audio_stream *stream,
799 const char *keys)
800{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700801 (void)stream;
802 (void)keys;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700803 return strdup("");
804}
805
806static int in_set_gain(struct audio_stream_in *stream, float gain)
807{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700808 (void)stream;
809 (void)gain;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700810 return 0;
811}
812
813static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
814 size_t bytes)
815{
816 ssize_t frames_read = -1977;
Stewart Milesf645c5e2014-05-01 09:03:27 -0700817 struct submix_stream_in * const in = audio_stream_in_get_submix_stream_in(stream);
818 struct submix_audio_device * const rsxadev = in->dev;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700819 const size_t frame_size = audio_stream_frame_size(&stream->common);
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700820 const size_t frames_to_read = bytes / frame_size;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700821
Stewart Milesc049a0a2014-05-01 09:03:27 -0700822 SUBMIX_ALOGV("in_read bytes=%zu", bytes);
Stewart Milesf645c5e2014-05-01 09:03:27 -0700823 pthread_mutex_lock(&rsxadev->lock);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700824
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700825 const bool output_standby_transition = (in->output_standby != in->dev->output_standby);
Stewart Milesf645c5e2014-05-01 09:03:27 -0700826 in->output_standby = rsxadev->output_standby;
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700827
Stewart Milesf645c5e2014-05-01 09:03:27 -0700828 if (rsxadev->input_standby || output_standby_transition) {
829 rsxadev->input_standby = false;
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700830 // keep track of when we exit input standby (== first read == start "real recording")
831 // or when we start recording silence, and reset projected time
832 int rc = clock_gettime(CLOCK_MONOTONIC, &in->record_start_time);
833 if (rc == 0) {
834 in->read_counter_frames = 0;
835 }
836 }
837
838 in->read_counter_frames += frames_to_read;
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700839 size_t remaining_frames = frames_to_read;
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800840
841 {
842 // about to read from audio source
Stewart Milesf645c5e2014-05-01 09:03:27 -0700843 sp<MonoPipeReader> source = rsxadev->rsxSource;
844 if (source == NULL) {
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800845 ALOGE("no audio pipe yet we're trying to read!");
Stewart Milesf645c5e2014-05-01 09:03:27 -0700846 pthread_mutex_unlock(&rsxadev->lock);
Stewart Miles3dd36f92014-05-01 09:03:27 -0700847 usleep(frames_to_read * 1000000 / in_get_sample_rate(&stream->common));
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800848 memset(buffer, 0, bytes);
849 return bytes;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700850 }
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800851
Stewart Milesf645c5e2014-05-01 09:03:27 -0700852 pthread_mutex_unlock(&rsxadev->lock);
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800853
854 // read the data from the pipe (it's non blocking)
855 int attempts = 0;
856 char* buff = (char*)buffer;
857 while ((remaining_frames > 0) && (attempts < MAX_READ_ATTEMPTS)) {
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800858 frames_read = source->read(buff, remaining_frames, AudioBufferProvider::kInvalidPTS);
Stewart Miles3dd36f92014-05-01 09:03:27 -0700859
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800860 if (frames_read > 0) {
861 remaining_frames -= frames_read;
862 buff += frames_read * frame_size;
Stewart Milesc049a0a2014-05-01 09:03:27 -0700863 SUBMIX_ALOGV(" in_read (att=%d) got %zd frames, remaining=%zu",
864 attempts, frames_read, remaining_frames);
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800865 } else {
Stewart Miles3dd36f92014-05-01 09:03:27 -0700866 attempts++;
Stewart Milesc049a0a2014-05-01 09:03:27 -0700867 SUBMIX_ALOGE(" in_read read returned %zd", frames_read);
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800868 usleep(READ_ATTEMPT_SLEEP_MS * 1000);
869 }
870 }
871 // done using the source
Stewart Milesf645c5e2014-05-01 09:03:27 -0700872 pthread_mutex_lock(&rsxadev->lock);
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800873 source.clear();
Stewart Milesf645c5e2014-05-01 09:03:27 -0700874 pthread_mutex_unlock(&rsxadev->lock);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700875 }
876
Jean-Michel Trivi6acd9662012-09-11 19:19:08 -0700877 if (remaining_frames > 0) {
Stewart Miles3dd36f92014-05-01 09:03:27 -0700878 const size_t remaining_bytes = remaining_frames * frame_size;
Stewart Milesc049a0a2014-05-01 09:03:27 -0700879 SUBMIX_ALOGV(" remaining_frames = %zu", remaining_frames);
Stewart Miles3dd36f92014-05-01 09:03:27 -0700880 memset(((char*)buffer)+ bytes - remaining_bytes, 0, remaining_bytes);
Jean-Michel Trivi6acd9662012-09-11 19:19:08 -0700881 }
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700882
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700883 // compute how much we need to sleep after reading the data by comparing the wall clock with
884 // the projected time at which we should return.
885 struct timespec time_after_read;// wall clock after reading from the pipe
886 struct timespec record_duration;// observed record duration
887 int rc = clock_gettime(CLOCK_MONOTONIC, &time_after_read);
888 const uint32_t sample_rate = in_get_sample_rate(&stream->common);
889 if (rc == 0) {
890 // for how long have we been recording?
891 record_duration.tv_sec = time_after_read.tv_sec - in->record_start_time.tv_sec;
892 record_duration.tv_nsec = time_after_read.tv_nsec - in->record_start_time.tv_nsec;
893 if (record_duration.tv_nsec < 0) {
894 record_duration.tv_sec--;
895 record_duration.tv_nsec += 1000000000;
896 }
897
Stewart Milesf645c5e2014-05-01 09:03:27 -0700898 // read_counter_frames contains the number of frames that have been read since the
899 // beginning of recording (including this call): it's converted to usec and compared to
900 // how long we've been recording for, which gives us how long we must wait to sync the
901 // projected recording time, and the observed recording time.
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700902 long projected_vs_observed_offset_us =
903 ((int64_t)(in->read_counter_frames
904 - (record_duration.tv_sec*sample_rate)))
905 * 1000000 / sample_rate
906 - (record_duration.tv_nsec / 1000);
907
Stewart Milesc049a0a2014-05-01 09:03:27 -0700908 SUBMIX_ALOGV(" record duration %5lds %3ldms, will wait: %7ldus",
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700909 record_duration.tv_sec, record_duration.tv_nsec/1000000,
910 projected_vs_observed_offset_us);
911 if (projected_vs_observed_offset_us > 0) {
912 usleep(projected_vs_observed_offset_us);
913 }
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700914 }
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700915
Stewart Milesc049a0a2014-05-01 09:03:27 -0700916 SUBMIX_ALOGV("in_read returns %zu", bytes);
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700917 return bytes;
918
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700919}
920
921static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
922{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700923 (void)stream;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700924 return 0;
925}
926
927static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
928{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700929 (void)stream;
930 (void)effect;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700931 return 0;
932}
933
934static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
935{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700936 (void)stream;
937 (void)effect;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700938 return 0;
939}
940
941static int adev_open_output_stream(struct audio_hw_device *dev,
942 audio_io_handle_t handle,
943 audio_devices_t devices,
944 audio_output_flags_t flags,
945 struct audio_config *config,
946 struct audio_stream_out **stream_out)
947{
Stewart Milesf645c5e2014-05-01 09:03:27 -0700948 struct submix_audio_device * const rsxadev = audio_hw_device_get_submix_audio_device(dev);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700949 ALOGV("adev_open_output_stream()");
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700950 struct submix_stream_out *out;
Stewart Milesc049a0a2014-05-01 09:03:27 -0700951 (void)handle;
952 (void)devices;
953 (void)flags;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700954
Stewart Miles3dd36f92014-05-01 09:03:27 -0700955 *stream_out = NULL;
956
Stewart Miles70726842014-05-01 09:03:27 -0700957 // Make sure it's possible to open the device given the current audio config.
958 submix_sanitize_config(config, false);
959 if (!submix_open_validate(rsxadev, &rsxadev->lock, config, false)) {
960 ALOGE("adev_open_output_stream(): Unable to open output stream.");
961 return -EINVAL;
962 }
963
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700964 out = (struct submix_stream_out *)calloc(1, sizeof(struct submix_stream_out));
Stewart Miles3dd36f92014-05-01 09:03:27 -0700965 if (!out) return -ENOMEM;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700966
Stewart Miles568e66f2014-05-01 09:03:27 -0700967 // Initialize the function pointer tables (v-tables).
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700968 out->stream.common.get_sample_rate = out_get_sample_rate;
969 out->stream.common.set_sample_rate = out_set_sample_rate;
970 out->stream.common.get_buffer_size = out_get_buffer_size;
971 out->stream.common.get_channels = out_get_channels;
972 out->stream.common.get_format = out_get_format;
973 out->stream.common.set_format = out_set_format;
974 out->stream.common.standby = out_standby;
975 out->stream.common.dump = out_dump;
976 out->stream.common.set_parameters = out_set_parameters;
977 out->stream.common.get_parameters = out_get_parameters;
978 out->stream.common.add_audio_effect = out_add_audio_effect;
979 out->stream.common.remove_audio_effect = out_remove_audio_effect;
980 out->stream.get_latency = out_get_latency;
981 out->stream.set_volume = out_set_volume;
982 out->stream.write = out_write;
983 out->stream.get_render_position = out_get_render_position;
984 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
985
Stewart Miles3dd36f92014-05-01 09:03:27 -0700986 // If the sink has been shutdown, delete the pipe so that it's recreated.
987 pthread_mutex_lock(&rsxadev->lock);
988 if (rsxadev->rsxSink != NULL && rsxadev->rsxSink->isShutdown()) {
989 submix_audio_device_release_pipe(rsxadev);
990 }
991 pthread_mutex_unlock(&rsxadev->lock);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700992
Stewart Miles568e66f2014-05-01 09:03:27 -0700993 // Store a pointer to the device from the output stream.
994 out->dev = rsxadev;
Stewart Miles3dd36f92014-05-01 09:03:27 -0700995 // Initialize the pipe.
996 ALOGV("adev_open_output_stream(): Initializing pipe");
997 submix_audio_device_create_pipe(rsxadev, config, DEFAULT_PIPE_SIZE_IN_FRAMES,
998 DEFAULT_PIPE_PERIOD_COUNT, NULL, out);
Stewart Miles568e66f2014-05-01 09:03:27 -0700999 // Return the output stream.
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001000 *stream_out = &out->stream;
1001
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001002 return 0;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001003}
1004
1005static void adev_close_output_stream(struct audio_hw_device *dev,
1006 struct audio_stream_out *stream)
1007{
Stewart Miles3dd36f92014-05-01 09:03:27 -07001008 struct submix_stream_out * const out = audio_stream_out_get_submix_stream_out(stream);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001009 ALOGV("adev_close_output_stream()");
Stewart Miles3dd36f92014-05-01 09:03:27 -07001010 submix_audio_device_destroy_pipe(audio_hw_device_get_submix_audio_device(dev), NULL, out);
1011 free(out);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001012}
1013
1014static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
1015{
Stewart Milesc049a0a2014-05-01 09:03:27 -07001016 (void)dev;
1017 (void)kvpairs;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001018 return -ENOSYS;
1019}
1020
1021static char * adev_get_parameters(const struct audio_hw_device *dev,
1022 const char *keys)
1023{
Stewart Milesc049a0a2014-05-01 09:03:27 -07001024 (void)dev;
1025 (void)keys;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001026 return strdup("");;
1027}
1028
1029static int adev_init_check(const struct audio_hw_device *dev)
1030{
1031 ALOGI("adev_init_check()");
Stewart Milesc049a0a2014-05-01 09:03:27 -07001032 (void)dev;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001033 return 0;
1034}
1035
1036static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
1037{
Stewart Milesc049a0a2014-05-01 09:03:27 -07001038 (void)dev;
1039 (void)volume;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001040 return -ENOSYS;
1041}
1042
1043static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
1044{
Stewart Milesc049a0a2014-05-01 09:03:27 -07001045 (void)dev;
1046 (void)volume;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001047 return -ENOSYS;
1048}
1049
1050static int adev_get_master_volume(struct audio_hw_device *dev, float *volume)
1051{
Stewart Milesc049a0a2014-05-01 09:03:27 -07001052 (void)dev;
1053 (void)volume;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001054 return -ENOSYS;
1055}
1056
1057static int adev_set_master_mute(struct audio_hw_device *dev, bool muted)
1058{
Stewart Milesc049a0a2014-05-01 09:03:27 -07001059 (void)dev;
1060 (void)muted;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001061 return -ENOSYS;
1062}
1063
1064static int adev_get_master_mute(struct audio_hw_device *dev, bool *muted)
1065{
Stewart Milesc049a0a2014-05-01 09:03:27 -07001066 (void)dev;
1067 (void)muted;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001068 return -ENOSYS;
1069}
1070
1071static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
1072{
Stewart Milesc049a0a2014-05-01 09:03:27 -07001073 (void)dev;
1074 (void)mode;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001075 return 0;
1076}
1077
1078static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
1079{
Stewart Milesc049a0a2014-05-01 09:03:27 -07001080 (void)dev;
1081 (void)state;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001082 return -ENOSYS;
1083}
1084
1085static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
1086{
Stewart Milesc049a0a2014-05-01 09:03:27 -07001087 (void)dev;
1088 (void)state;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001089 return -ENOSYS;
1090}
1091
1092static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
1093 const struct audio_config *config)
1094{
Stewart Miles568e66f2014-05-01 09:03:27 -07001095 if (audio_is_linear_pcm(config->format)) {
1096 const size_t buffer_period_size_frames =
1097 audio_hw_device_get_submix_audio_device(const_cast<struct audio_hw_device*>(dev))->
Stewart Miles3dd36f92014-05-01 09:03:27 -07001098 config.buffer_period_size_frames;
Stewart Miles568e66f2014-05-01 09:03:27 -07001099 const size_t frame_size_in_bytes = get_channel_count_from_mask(config->channel_mask) *
1100 audio_bytes_per_sample(config->format);
1101 const size_t buffer_size = buffer_period_size_frames * frame_size_in_bytes;
1102 SUBMIX_ALOGV("out_get_buffer_size() returns %zu bytes, %zu frames",
1103 buffer_size, buffer_period_size_frames);
1104 return buffer_size;
1105 }
1106 return 0;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001107}
1108
1109static int adev_open_input_stream(struct audio_hw_device *dev,
1110 audio_io_handle_t handle,
1111 audio_devices_t devices,
1112 struct audio_config *config,
1113 struct audio_stream_in **stream_in)
1114{
Stewart Milesf645c5e2014-05-01 09:03:27 -07001115 struct submix_audio_device *rsxadev = audio_hw_device_get_submix_audio_device(dev);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001116 struct submix_stream_in *in;
Stewart Miles568e66f2014-05-01 09:03:27 -07001117 ALOGI("adev_open_input_stream()");
Stewart Milesc049a0a2014-05-01 09:03:27 -07001118 (void)handle;
1119 (void)devices;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001120
Stewart Miles3dd36f92014-05-01 09:03:27 -07001121 *stream_in = NULL;
1122
Stewart Miles70726842014-05-01 09:03:27 -07001123 // Make sure it's possible to open the device given the current audio config.
1124 submix_sanitize_config(config, true);
1125 if (!submix_open_validate(rsxadev, &rsxadev->lock, config, true)) {
1126 ALOGE("adev_open_input_stream(): Unable to open input stream.");
1127 return -EINVAL;
1128 }
1129
Stewart Miles3dd36f92014-05-01 09:03:27 -07001130#if ENABLE_LEGACY_INPUT_OPEN
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001131 pthread_mutex_lock(&rsxadev->lock);
Stewart Miles3dd36f92014-05-01 09:03:27 -07001132 in = rsxadev->input;
1133 if (in) {
1134 in->ref_count++;
1135 sp<MonoPipe> sink = rsxadev->rsxSink;
1136 ALOG_ASSERT(sink != NULL);
1137 // If the sink has been shutdown, delete the pipe.
1138 if (sink->isShutdown()) submix_audio_device_release_pipe(rsxadev);
1139 }
1140 pthread_mutex_unlock(&rsxadev->lock);
1141#else
1142 in = NULL;
1143#endif // ENABLE_LEGACY_INPUT_OPEN
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001144
Stewart Miles3dd36f92014-05-01 09:03:27 -07001145 if (!in) {
1146 in = (struct submix_stream_in *)calloc(1, sizeof(struct submix_stream_in));
1147 if (!in) return -ENOMEM;
1148 in->ref_count = 1;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001149
Stewart Miles3dd36f92014-05-01 09:03:27 -07001150 // Initialize the function pointer tables (v-tables).
1151 in->stream.common.get_sample_rate = in_get_sample_rate;
1152 in->stream.common.set_sample_rate = in_set_sample_rate;
1153 in->stream.common.get_buffer_size = in_get_buffer_size;
1154 in->stream.common.get_channels = in_get_channels;
1155 in->stream.common.get_format = in_get_format;
1156 in->stream.common.set_format = in_set_format;
1157 in->stream.common.standby = in_standby;
1158 in->stream.common.dump = in_dump;
1159 in->stream.common.set_parameters = in_set_parameters;
1160 in->stream.common.get_parameters = in_get_parameters;
1161 in->stream.common.add_audio_effect = in_add_audio_effect;
1162 in->stream.common.remove_audio_effect = in_remove_audio_effect;
1163 in->stream.set_gain = in_set_gain;
1164 in->stream.read = in_read;
1165 in->stream.get_input_frames_lost = in_get_input_frames_lost;
1166 }
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001167
Stewart Miles568e66f2014-05-01 09:03:27 -07001168 // Initialize the input stream.
Jean-Michel Trivieec87702012-09-17 09:59:42 -07001169 in->read_counter_frames = 0;
1170 in->output_standby = rsxadev->output_standby;
Stewart Miles3dd36f92014-05-01 09:03:27 -07001171 in->dev = rsxadev;
1172 // Initialize the pipe.
1173 submix_audio_device_create_pipe(rsxadev, config, DEFAULT_PIPE_SIZE_IN_FRAMES,
1174 DEFAULT_PIPE_PERIOD_COUNT, in, NULL);
1175 // Return the input stream.
1176 *stream_in = &in->stream;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001177
1178 return 0;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001179}
1180
1181static void adev_close_input_stream(struct audio_hw_device *dev,
Stewart Milesc049a0a2014-05-01 09:03:27 -07001182 struct audio_stream_in *stream)
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001183{
Stewart Miles3dd36f92014-05-01 09:03:27 -07001184 struct submix_stream_in * const in = audio_stream_in_get_submix_stream_in(stream);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001185 ALOGV("adev_close_input_stream()");
Stewart Miles3dd36f92014-05-01 09:03:27 -07001186 submix_audio_device_destroy_pipe(audio_hw_device_get_submix_audio_device(dev), in, NULL);
1187#if ENABLE_LEGACY_INPUT_OPEN
1188 if (in->ref_count == 0) free(in);
1189#else
1190 free(in);
1191#endif // ENABLE_LEGACY_INPUT_OPEN
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001192}
1193
1194static int adev_dump(const audio_hw_device_t *device, int fd)
1195{
Stewart Milesc049a0a2014-05-01 09:03:27 -07001196 (void)device;
1197 (void)fd;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001198 return 0;
1199}
1200
1201static int adev_close(hw_device_t *device)
1202{
1203 ALOGI("adev_close()");
1204 free(device);
1205 return 0;
1206}
1207
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001208static int adev_open(const hw_module_t* module, const char* name,
1209 hw_device_t** device)
1210{
1211 ALOGI("adev_open(name=%s)", name);
1212 struct submix_audio_device *rsxadev;
1213
1214 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
1215 return -EINVAL;
1216
1217 rsxadev = (submix_audio_device*) calloc(1, sizeof(struct submix_audio_device));
1218 if (!rsxadev)
1219 return -ENOMEM;
1220
1221 rsxadev->device.common.tag = HARDWARE_DEVICE_TAG;
Eric Laurent5d85c532012-09-10 10:36:09 -07001222 rsxadev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001223 rsxadev->device.common.module = (struct hw_module_t *) module;
1224 rsxadev->device.common.close = adev_close;
1225
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001226 rsxadev->device.init_check = adev_init_check;
1227 rsxadev->device.set_voice_volume = adev_set_voice_volume;
1228 rsxadev->device.set_master_volume = adev_set_master_volume;
1229 rsxadev->device.get_master_volume = adev_get_master_volume;
1230 rsxadev->device.set_master_mute = adev_set_master_mute;
1231 rsxadev->device.get_master_mute = adev_get_master_mute;
1232 rsxadev->device.set_mode = adev_set_mode;
1233 rsxadev->device.set_mic_mute = adev_set_mic_mute;
1234 rsxadev->device.get_mic_mute = adev_get_mic_mute;
1235 rsxadev->device.set_parameters = adev_set_parameters;
1236 rsxadev->device.get_parameters = adev_get_parameters;
1237 rsxadev->device.get_input_buffer_size = adev_get_input_buffer_size;
1238 rsxadev->device.open_output_stream = adev_open_output_stream;
1239 rsxadev->device.close_output_stream = adev_close_output_stream;
1240 rsxadev->device.open_input_stream = adev_open_input_stream;
1241 rsxadev->device.close_input_stream = adev_close_input_stream;
1242 rsxadev->device.dump = adev_dump;
1243
Jean-Michel Trivieec87702012-09-17 09:59:42 -07001244 rsxadev->input_standby = true;
1245 rsxadev->output_standby = true;
1246
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001247 *device = &rsxadev->device.common;
1248
1249 return 0;
1250}
1251
1252static struct hw_module_methods_t hal_module_methods = {
1253 /* open */ adev_open,
1254};
1255
1256struct audio_module HAL_MODULE_INFO_SYM = {
1257 /* common */ {
1258 /* tag */ HARDWARE_MODULE_TAG,
1259 /* module_api_version */ AUDIO_MODULE_API_VERSION_0_1,
1260 /* hal_api_version */ HARDWARE_HAL_API_VERSION,
1261 /* id */ AUDIO_HARDWARE_MODULE_ID,
1262 /* name */ "Wifi Display audio HAL",
1263 /* author */ "The Android Open Source Project",
1264 /* methods */ &hal_module_methods,
1265 /* dso */ NULL,
1266 /* reserved */ { 0 },
1267 },
1268};
1269
1270} //namespace android
1271
1272} //extern "C"