blob: 8014d18945e427d688c5219efb6f378875fb3c48 [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 Milesf645c5e2014-05-01 09:03:27 -0700627 pthread_mutex_unlock(&rsxadev->lock);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700628
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700629 written_frames = sink->write(buffer, frames);
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800630
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700631 if (written_frames < 0) {
632 if (written_frames == (ssize_t)NEGOTIATE) {
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700633 ALOGE("out_write() write to pipe returned NEGOTIATE");
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700634
Stewart Milesf645c5e2014-05-01 09:03:27 -0700635 pthread_mutex_lock(&rsxadev->lock);
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800636 sink.clear();
Stewart Milesf645c5e2014-05-01 09:03:27 -0700637 pthread_mutex_unlock(&rsxadev->lock);
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700638
639 written_frames = 0;
Jean-Michel Trivi6acd9662012-09-11 19:19:08 -0700640 return 0;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700641 } else {
642 // write() returned UNDERRUN or WOULD_BLOCK, retry
Colin Cross5685a082014-04-18 15:45:42 -0700643 ALOGE("out_write() write to pipe returned unexpected %zd", written_frames);
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700644 written_frames = sink->write(buffer, frames);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700645 }
646 }
647
Stewart Milesf645c5e2014-05-01 09:03:27 -0700648 pthread_mutex_lock(&rsxadev->lock);
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800649 sink.clear();
Stewart Milesf645c5e2014-05-01 09:03:27 -0700650 pthread_mutex_unlock(&rsxadev->lock);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700651
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700652 if (written_frames < 0) {
Colin Cross5685a082014-04-18 15:45:42 -0700653 ALOGE("out_write() failed writing to pipe with %zd", written_frames);
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700654 return 0;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700655 }
Stewart Milesc049a0a2014-05-01 09:03:27 -0700656 const ssize_t written_bytes = written_frames * frame_size;
657 SUBMIX_ALOGV("out_write() wrote %zd bytes %zd frames)", written_bytes, written_frames);
658 return written_bytes;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700659}
660
661static int out_get_render_position(const struct audio_stream_out *stream,
662 uint32_t *dsp_frames)
663{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700664 (void)stream;
665 (void)dsp_frames;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700666 return -EINVAL;
667}
668
669static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
670{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700671 (void)stream;
672 (void)effect;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700673 return 0;
674}
675
676static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
677{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700678 (void)stream;
679 (void)effect;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700680 return 0;
681}
682
683static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
684 int64_t *timestamp)
685{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700686 (void)stream;
687 (void)timestamp;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700688 return -EINVAL;
689}
690
691/** audio_stream_in implementation **/
692static uint32_t in_get_sample_rate(const struct audio_stream *stream)
693{
Stewart Milesf645c5e2014-05-01 09:03:27 -0700694 const struct submix_stream_in * const in = audio_stream_get_submix_stream_in(
695 const_cast<struct audio_stream*>(stream));
Stewart Miles70726842014-05-01 09:03:27 -0700696 SUBMIX_ALOGV("in_get_sample_rate() returns %u", in->dev->config.common.sample_rate);
697 return in->dev->config.common.sample_rate;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700698}
699
700static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
701{
Stewart Miles568e66f2014-05-01 09:03:27 -0700702 const struct submix_stream_in * const in = audio_stream_get_submix_stream_in(stream);
Stewart Miles70726842014-05-01 09:03:27 -0700703 if (!sample_rate_supported(rate)) {
704 ALOGE("in_set_sample_rate(rate=%u) rate unsupported", rate);
705 return -ENOSYS;
706 }
707 in->dev->config.common.sample_rate = rate;
Stewart Miles568e66f2014-05-01 09:03:27 -0700708 SUBMIX_ALOGV("in_set_sample_rate() set %u", rate);
709 return 0;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700710}
711
712static size_t in_get_buffer_size(const struct audio_stream *stream)
713{
Stewart Milesf645c5e2014-05-01 09:03:27 -0700714 const struct submix_stream_in * const in = audio_stream_get_submix_stream_in(
715 const_cast<struct audio_stream*>(stream));
Stewart Miles3dd36f92014-05-01 09:03:27 -0700716 const size_t buffer_size = in->dev->config.buffer_period_size_frames *
717 audio_stream_frame_size(stream);
Stewart Miles568e66f2014-05-01 09:03:27 -0700718 SUBMIX_ALOGV("in_get_buffer_size() returns %zu", buffer_size);
719 return buffer_size;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700720}
721
722static audio_channel_mask_t in_get_channels(const struct audio_stream *stream)
723{
Stewart Miles70726842014-05-01 09:03:27 -0700724 const struct submix_stream_in * const in = audio_stream_get_submix_stream_in(
725 const_cast<struct audio_stream*>(stream));
726 const audio_channel_mask_t channel_mask = in->dev->config.input_channel_mask;
727 SUBMIX_ALOGV("in_get_channels() returns %x", channel_mask);
728 return channel_mask;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700729}
730
731static audio_format_t in_get_format(const struct audio_stream *stream)
732{
Stewart Miles568e66f2014-05-01 09:03:27 -0700733 const struct submix_stream_in * const in = audio_stream_get_submix_stream_in(
Stewart Miles70726842014-05-01 09:03:27 -0700734 const_cast<struct audio_stream*>(stream));
735 const audio_format_t format = in->dev->config.common.format;
Stewart Miles568e66f2014-05-01 09:03:27 -0700736 SUBMIX_ALOGV("in_get_format() returns %x", format);
737 return format;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700738}
739
740static int in_set_format(struct audio_stream *stream, audio_format_t format)
741{
Stewart Miles568e66f2014-05-01 09:03:27 -0700742 const struct submix_stream_in * const in = audio_stream_get_submix_stream_in(stream);
Stewart Miles70726842014-05-01 09:03:27 -0700743 if (format != in->dev->config.common.format) {
Stewart Milesc049a0a2014-05-01 09:03:27 -0700744 ALOGE("in_set_format(format=%x) format unsupported", format);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700745 return -ENOSYS;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700746 }
Stewart Milesc049a0a2014-05-01 09:03:27 -0700747 SUBMIX_ALOGV("in_set_format(format=%x)", format);
748 return 0;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700749}
750
751static int in_standby(struct audio_stream *stream)
752{
Stewart Milesf645c5e2014-05-01 09:03:27 -0700753 struct submix_audio_device * const rsxadev = audio_stream_get_submix_stream_in(stream)->dev;
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700754 ALOGI("in_standby()");
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700755
Stewart Milesf645c5e2014-05-01 09:03:27 -0700756 pthread_mutex_lock(&rsxadev->lock);
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700757
Stewart Milesf645c5e2014-05-01 09:03:27 -0700758 rsxadev->input_standby = true;
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700759
Stewart Milesf645c5e2014-05-01 09:03:27 -0700760 pthread_mutex_unlock(&rsxadev->lock);
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700761
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700762 return 0;
763}
764
765static int in_dump(const struct audio_stream *stream, int fd)
766{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700767 (void)stream;
768 (void)fd;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700769 return 0;
770}
771
772static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
773{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700774 (void)stream;
775 (void)kvpairs;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700776 return 0;
777}
778
779static char * in_get_parameters(const struct audio_stream *stream,
780 const char *keys)
781{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700782 (void)stream;
783 (void)keys;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700784 return strdup("");
785}
786
787static int in_set_gain(struct audio_stream_in *stream, float gain)
788{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700789 (void)stream;
790 (void)gain;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700791 return 0;
792}
793
794static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
795 size_t bytes)
796{
797 ssize_t frames_read = -1977;
Stewart Milesf645c5e2014-05-01 09:03:27 -0700798 struct submix_stream_in * const in = audio_stream_in_get_submix_stream_in(stream);
799 struct submix_audio_device * const rsxadev = in->dev;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700800 const size_t frame_size = audio_stream_frame_size(&stream->common);
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700801 const size_t frames_to_read = bytes / frame_size;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700802
Stewart Milesc049a0a2014-05-01 09:03:27 -0700803 SUBMIX_ALOGV("in_read bytes=%zu", bytes);
Stewart Milesf645c5e2014-05-01 09:03:27 -0700804 pthread_mutex_lock(&rsxadev->lock);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700805
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700806 const bool output_standby_transition = (in->output_standby != in->dev->output_standby);
Stewart Milesf645c5e2014-05-01 09:03:27 -0700807 in->output_standby = rsxadev->output_standby;
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700808
Stewart Milesf645c5e2014-05-01 09:03:27 -0700809 if (rsxadev->input_standby || output_standby_transition) {
810 rsxadev->input_standby = false;
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700811 // keep track of when we exit input standby (== first read == start "real recording")
812 // or when we start recording silence, and reset projected time
813 int rc = clock_gettime(CLOCK_MONOTONIC, &in->record_start_time);
814 if (rc == 0) {
815 in->read_counter_frames = 0;
816 }
817 }
818
819 in->read_counter_frames += frames_to_read;
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700820 size_t remaining_frames = frames_to_read;
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800821
822 {
823 // about to read from audio source
Stewart Milesf645c5e2014-05-01 09:03:27 -0700824 sp<MonoPipeReader> source = rsxadev->rsxSource;
825 if (source == NULL) {
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800826 ALOGE("no audio pipe yet we're trying to read!");
Stewart Milesf645c5e2014-05-01 09:03:27 -0700827 pthread_mutex_unlock(&rsxadev->lock);
Stewart Miles3dd36f92014-05-01 09:03:27 -0700828 usleep(frames_to_read * 1000000 / in_get_sample_rate(&stream->common));
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800829 memset(buffer, 0, bytes);
830 return bytes;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700831 }
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800832
Stewart Milesf645c5e2014-05-01 09:03:27 -0700833 pthread_mutex_unlock(&rsxadev->lock);
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800834
835 // read the data from the pipe (it's non blocking)
836 int attempts = 0;
837 char* buff = (char*)buffer;
838 while ((remaining_frames > 0) && (attempts < MAX_READ_ATTEMPTS)) {
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800839 frames_read = source->read(buff, remaining_frames, AudioBufferProvider::kInvalidPTS);
Stewart Miles3dd36f92014-05-01 09:03:27 -0700840
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800841 if (frames_read > 0) {
842 remaining_frames -= frames_read;
843 buff += frames_read * frame_size;
Stewart Milesc049a0a2014-05-01 09:03:27 -0700844 SUBMIX_ALOGV(" in_read (att=%d) got %zd frames, remaining=%zu",
845 attempts, frames_read, remaining_frames);
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800846 } else {
Stewart Miles3dd36f92014-05-01 09:03:27 -0700847 attempts++;
Stewart Milesc049a0a2014-05-01 09:03:27 -0700848 SUBMIX_ALOGE(" in_read read returned %zd", frames_read);
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800849 usleep(READ_ATTEMPT_SLEEP_MS * 1000);
850 }
851 }
852 // done using the source
Stewart Milesf645c5e2014-05-01 09:03:27 -0700853 pthread_mutex_lock(&rsxadev->lock);
Jean-Michel Trivieafbfa42012-12-18 11:30:33 -0800854 source.clear();
Stewart Milesf645c5e2014-05-01 09:03:27 -0700855 pthread_mutex_unlock(&rsxadev->lock);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700856 }
857
Jean-Michel Trivi6acd9662012-09-11 19:19:08 -0700858 if (remaining_frames > 0) {
Stewart Miles3dd36f92014-05-01 09:03:27 -0700859 const size_t remaining_bytes = remaining_frames * frame_size;
Stewart Milesc049a0a2014-05-01 09:03:27 -0700860 SUBMIX_ALOGV(" remaining_frames = %zu", remaining_frames);
Stewart Miles3dd36f92014-05-01 09:03:27 -0700861 memset(((char*)buffer)+ bytes - remaining_bytes, 0, remaining_bytes);
Jean-Michel Trivi6acd9662012-09-11 19:19:08 -0700862 }
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700863
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700864 // compute how much we need to sleep after reading the data by comparing the wall clock with
865 // the projected time at which we should return.
866 struct timespec time_after_read;// wall clock after reading from the pipe
867 struct timespec record_duration;// observed record duration
868 int rc = clock_gettime(CLOCK_MONOTONIC, &time_after_read);
869 const uint32_t sample_rate = in_get_sample_rate(&stream->common);
870 if (rc == 0) {
871 // for how long have we been recording?
872 record_duration.tv_sec = time_after_read.tv_sec - in->record_start_time.tv_sec;
873 record_duration.tv_nsec = time_after_read.tv_nsec - in->record_start_time.tv_nsec;
874 if (record_duration.tv_nsec < 0) {
875 record_duration.tv_sec--;
876 record_duration.tv_nsec += 1000000000;
877 }
878
Stewart Milesf645c5e2014-05-01 09:03:27 -0700879 // read_counter_frames contains the number of frames that have been read since the
880 // beginning of recording (including this call): it's converted to usec and compared to
881 // how long we've been recording for, which gives us how long we must wait to sync the
882 // projected recording time, and the observed recording time.
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700883 long projected_vs_observed_offset_us =
884 ((int64_t)(in->read_counter_frames
885 - (record_duration.tv_sec*sample_rate)))
886 * 1000000 / sample_rate
887 - (record_duration.tv_nsec / 1000);
888
Stewart Milesc049a0a2014-05-01 09:03:27 -0700889 SUBMIX_ALOGV(" record duration %5lds %3ldms, will wait: %7ldus",
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700890 record_duration.tv_sec, record_duration.tv_nsec/1000000,
891 projected_vs_observed_offset_us);
892 if (projected_vs_observed_offset_us > 0) {
893 usleep(projected_vs_observed_offset_us);
894 }
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700895 }
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700896
Stewart Milesc049a0a2014-05-01 09:03:27 -0700897 SUBMIX_ALOGV("in_read returns %zu", bytes);
Jean-Michel Trivieec87702012-09-17 09:59:42 -0700898 return bytes;
899
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700900}
901
902static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
903{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700904 (void)stream;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700905 return 0;
906}
907
908static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
909{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700910 (void)stream;
911 (void)effect;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700912 return 0;
913}
914
915static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
916{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700917 (void)stream;
918 (void)effect;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700919 return 0;
920}
921
922static int adev_open_output_stream(struct audio_hw_device *dev,
923 audio_io_handle_t handle,
924 audio_devices_t devices,
925 audio_output_flags_t flags,
926 struct audio_config *config,
927 struct audio_stream_out **stream_out)
928{
Stewart Milesf645c5e2014-05-01 09:03:27 -0700929 struct submix_audio_device * const rsxadev = audio_hw_device_get_submix_audio_device(dev);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700930 ALOGV("adev_open_output_stream()");
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700931 struct submix_stream_out *out;
Stewart Milesc049a0a2014-05-01 09:03:27 -0700932 (void)handle;
933 (void)devices;
934 (void)flags;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700935
Stewart Miles3dd36f92014-05-01 09:03:27 -0700936 *stream_out = NULL;
937
Stewart Miles70726842014-05-01 09:03:27 -0700938 // Make sure it's possible to open the device given the current audio config.
939 submix_sanitize_config(config, false);
940 if (!submix_open_validate(rsxadev, &rsxadev->lock, config, false)) {
941 ALOGE("adev_open_output_stream(): Unable to open output stream.");
942 return -EINVAL;
943 }
944
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700945 out = (struct submix_stream_out *)calloc(1, sizeof(struct submix_stream_out));
Stewart Miles3dd36f92014-05-01 09:03:27 -0700946 if (!out) return -ENOMEM;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700947
Stewart Miles568e66f2014-05-01 09:03:27 -0700948 // Initialize the function pointer tables (v-tables).
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700949 out->stream.common.get_sample_rate = out_get_sample_rate;
950 out->stream.common.set_sample_rate = out_set_sample_rate;
951 out->stream.common.get_buffer_size = out_get_buffer_size;
952 out->stream.common.get_channels = out_get_channels;
953 out->stream.common.get_format = out_get_format;
954 out->stream.common.set_format = out_set_format;
955 out->stream.common.standby = out_standby;
956 out->stream.common.dump = out_dump;
957 out->stream.common.set_parameters = out_set_parameters;
958 out->stream.common.get_parameters = out_get_parameters;
959 out->stream.common.add_audio_effect = out_add_audio_effect;
960 out->stream.common.remove_audio_effect = out_remove_audio_effect;
961 out->stream.get_latency = out_get_latency;
962 out->stream.set_volume = out_set_volume;
963 out->stream.write = out_write;
964 out->stream.get_render_position = out_get_render_position;
965 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
966
Stewart Miles3dd36f92014-05-01 09:03:27 -0700967 // If the sink has been shutdown, delete the pipe so that it's recreated.
968 pthread_mutex_lock(&rsxadev->lock);
969 if (rsxadev->rsxSink != NULL && rsxadev->rsxSink->isShutdown()) {
970 submix_audio_device_release_pipe(rsxadev);
971 }
972 pthread_mutex_unlock(&rsxadev->lock);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700973
Stewart Miles568e66f2014-05-01 09:03:27 -0700974 // Store a pointer to the device from the output stream.
975 out->dev = rsxadev;
Stewart Miles3dd36f92014-05-01 09:03:27 -0700976 // Initialize the pipe.
977 ALOGV("adev_open_output_stream(): Initializing pipe");
978 submix_audio_device_create_pipe(rsxadev, config, DEFAULT_PIPE_SIZE_IN_FRAMES,
979 DEFAULT_PIPE_PERIOD_COUNT, NULL, out);
Stewart Miles568e66f2014-05-01 09:03:27 -0700980 // Return the output stream.
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700981 *stream_out = &out->stream;
982
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700983 return 0;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700984}
985
986static void adev_close_output_stream(struct audio_hw_device *dev,
987 struct audio_stream_out *stream)
988{
Stewart Miles3dd36f92014-05-01 09:03:27 -0700989 struct submix_stream_out * const out = audio_stream_out_get_submix_stream_out(stream);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700990 ALOGV("adev_close_output_stream()");
Stewart Miles3dd36f92014-05-01 09:03:27 -0700991 submix_audio_device_destroy_pipe(audio_hw_device_get_submix_audio_device(dev), NULL, out);
992 free(out);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700993}
994
995static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
996{
Stewart Milesc049a0a2014-05-01 09:03:27 -0700997 (void)dev;
998 (void)kvpairs;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -0700999 return -ENOSYS;
1000}
1001
1002static char * adev_get_parameters(const struct audio_hw_device *dev,
1003 const char *keys)
1004{
Stewart Milesc049a0a2014-05-01 09:03:27 -07001005 (void)dev;
1006 (void)keys;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001007 return strdup("");;
1008}
1009
1010static int adev_init_check(const struct audio_hw_device *dev)
1011{
1012 ALOGI("adev_init_check()");
Stewart Milesc049a0a2014-05-01 09:03:27 -07001013 (void)dev;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001014 return 0;
1015}
1016
1017static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
1018{
Stewart Milesc049a0a2014-05-01 09:03:27 -07001019 (void)dev;
1020 (void)volume;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001021 return -ENOSYS;
1022}
1023
1024static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
1025{
Stewart Milesc049a0a2014-05-01 09:03:27 -07001026 (void)dev;
1027 (void)volume;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001028 return -ENOSYS;
1029}
1030
1031static int adev_get_master_volume(struct audio_hw_device *dev, float *volume)
1032{
Stewart Milesc049a0a2014-05-01 09:03:27 -07001033 (void)dev;
1034 (void)volume;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001035 return -ENOSYS;
1036}
1037
1038static int adev_set_master_mute(struct audio_hw_device *dev, bool muted)
1039{
Stewart Milesc049a0a2014-05-01 09:03:27 -07001040 (void)dev;
1041 (void)muted;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001042 return -ENOSYS;
1043}
1044
1045static int adev_get_master_mute(struct audio_hw_device *dev, bool *muted)
1046{
Stewart Milesc049a0a2014-05-01 09:03:27 -07001047 (void)dev;
1048 (void)muted;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001049 return -ENOSYS;
1050}
1051
1052static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
1053{
Stewart Milesc049a0a2014-05-01 09:03:27 -07001054 (void)dev;
1055 (void)mode;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001056 return 0;
1057}
1058
1059static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
1060{
Stewart Milesc049a0a2014-05-01 09:03:27 -07001061 (void)dev;
1062 (void)state;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001063 return -ENOSYS;
1064}
1065
1066static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
1067{
Stewart Milesc049a0a2014-05-01 09:03:27 -07001068 (void)dev;
1069 (void)state;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001070 return -ENOSYS;
1071}
1072
1073static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
1074 const struct audio_config *config)
1075{
Stewart Miles568e66f2014-05-01 09:03:27 -07001076 if (audio_is_linear_pcm(config->format)) {
1077 const size_t buffer_period_size_frames =
1078 audio_hw_device_get_submix_audio_device(const_cast<struct audio_hw_device*>(dev))->
Stewart Miles3dd36f92014-05-01 09:03:27 -07001079 config.buffer_period_size_frames;
Stewart Miles568e66f2014-05-01 09:03:27 -07001080 const size_t frame_size_in_bytes = get_channel_count_from_mask(config->channel_mask) *
1081 audio_bytes_per_sample(config->format);
1082 const size_t buffer_size = buffer_period_size_frames * frame_size_in_bytes;
1083 SUBMIX_ALOGV("out_get_buffer_size() returns %zu bytes, %zu frames",
1084 buffer_size, buffer_period_size_frames);
1085 return buffer_size;
1086 }
1087 return 0;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001088}
1089
1090static int adev_open_input_stream(struct audio_hw_device *dev,
1091 audio_io_handle_t handle,
1092 audio_devices_t devices,
1093 struct audio_config *config,
1094 struct audio_stream_in **stream_in)
1095{
Stewart Milesf645c5e2014-05-01 09:03:27 -07001096 struct submix_audio_device *rsxadev = audio_hw_device_get_submix_audio_device(dev);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001097 struct submix_stream_in *in;
Stewart Miles568e66f2014-05-01 09:03:27 -07001098 ALOGI("adev_open_input_stream()");
Stewart Milesc049a0a2014-05-01 09:03:27 -07001099 (void)handle;
1100 (void)devices;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001101
Stewart Miles3dd36f92014-05-01 09:03:27 -07001102 *stream_in = NULL;
1103
Stewart Miles70726842014-05-01 09:03:27 -07001104 // Make sure it's possible to open the device given the current audio config.
1105 submix_sanitize_config(config, true);
1106 if (!submix_open_validate(rsxadev, &rsxadev->lock, config, true)) {
1107 ALOGE("adev_open_input_stream(): Unable to open input stream.");
1108 return -EINVAL;
1109 }
1110
Stewart Miles3dd36f92014-05-01 09:03:27 -07001111#if ENABLE_LEGACY_INPUT_OPEN
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001112 pthread_mutex_lock(&rsxadev->lock);
Stewart Miles3dd36f92014-05-01 09:03:27 -07001113 in = rsxadev->input;
1114 if (in) {
1115 in->ref_count++;
1116 sp<MonoPipe> sink = rsxadev->rsxSink;
1117 ALOG_ASSERT(sink != NULL);
1118 // If the sink has been shutdown, delete the pipe.
1119 if (sink->isShutdown()) submix_audio_device_release_pipe(rsxadev);
1120 }
1121 pthread_mutex_unlock(&rsxadev->lock);
1122#else
1123 in = NULL;
1124#endif // ENABLE_LEGACY_INPUT_OPEN
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001125
Stewart Miles3dd36f92014-05-01 09:03:27 -07001126 if (!in) {
1127 in = (struct submix_stream_in *)calloc(1, sizeof(struct submix_stream_in));
1128 if (!in) return -ENOMEM;
1129 in->ref_count = 1;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001130
Stewart Miles3dd36f92014-05-01 09:03:27 -07001131 // Initialize the function pointer tables (v-tables).
1132 in->stream.common.get_sample_rate = in_get_sample_rate;
1133 in->stream.common.set_sample_rate = in_set_sample_rate;
1134 in->stream.common.get_buffer_size = in_get_buffer_size;
1135 in->stream.common.get_channels = in_get_channels;
1136 in->stream.common.get_format = in_get_format;
1137 in->stream.common.set_format = in_set_format;
1138 in->stream.common.standby = in_standby;
1139 in->stream.common.dump = in_dump;
1140 in->stream.common.set_parameters = in_set_parameters;
1141 in->stream.common.get_parameters = in_get_parameters;
1142 in->stream.common.add_audio_effect = in_add_audio_effect;
1143 in->stream.common.remove_audio_effect = in_remove_audio_effect;
1144 in->stream.set_gain = in_set_gain;
1145 in->stream.read = in_read;
1146 in->stream.get_input_frames_lost = in_get_input_frames_lost;
1147 }
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001148
Stewart Miles568e66f2014-05-01 09:03:27 -07001149 // Initialize the input stream.
Jean-Michel Trivieec87702012-09-17 09:59:42 -07001150 in->read_counter_frames = 0;
1151 in->output_standby = rsxadev->output_standby;
Stewart Miles3dd36f92014-05-01 09:03:27 -07001152 in->dev = rsxadev;
1153 // Initialize the pipe.
1154 submix_audio_device_create_pipe(rsxadev, config, DEFAULT_PIPE_SIZE_IN_FRAMES,
1155 DEFAULT_PIPE_PERIOD_COUNT, in, NULL);
1156 // Return the input stream.
1157 *stream_in = &in->stream;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001158
1159 return 0;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001160}
1161
1162static void adev_close_input_stream(struct audio_hw_device *dev,
Stewart Milesc049a0a2014-05-01 09:03:27 -07001163 struct audio_stream_in *stream)
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001164{
Stewart Miles3dd36f92014-05-01 09:03:27 -07001165 struct submix_stream_in * const in = audio_stream_in_get_submix_stream_in(stream);
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001166 ALOGV("adev_close_input_stream()");
Stewart Miles3dd36f92014-05-01 09:03:27 -07001167 submix_audio_device_destroy_pipe(audio_hw_device_get_submix_audio_device(dev), in, NULL);
1168#if ENABLE_LEGACY_INPUT_OPEN
1169 if (in->ref_count == 0) free(in);
1170#else
1171 free(in);
1172#endif // ENABLE_LEGACY_INPUT_OPEN
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001173}
1174
1175static int adev_dump(const audio_hw_device_t *device, int fd)
1176{
Stewart Milesc049a0a2014-05-01 09:03:27 -07001177 (void)device;
1178 (void)fd;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001179 return 0;
1180}
1181
1182static int adev_close(hw_device_t *device)
1183{
1184 ALOGI("adev_close()");
1185 free(device);
1186 return 0;
1187}
1188
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001189static int adev_open(const hw_module_t* module, const char* name,
1190 hw_device_t** device)
1191{
1192 ALOGI("adev_open(name=%s)", name);
1193 struct submix_audio_device *rsxadev;
1194
1195 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
1196 return -EINVAL;
1197
1198 rsxadev = (submix_audio_device*) calloc(1, sizeof(struct submix_audio_device));
1199 if (!rsxadev)
1200 return -ENOMEM;
1201
1202 rsxadev->device.common.tag = HARDWARE_DEVICE_TAG;
Eric Laurent5d85c532012-09-10 10:36:09 -07001203 rsxadev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001204 rsxadev->device.common.module = (struct hw_module_t *) module;
1205 rsxadev->device.common.close = adev_close;
1206
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001207 rsxadev->device.init_check = adev_init_check;
1208 rsxadev->device.set_voice_volume = adev_set_voice_volume;
1209 rsxadev->device.set_master_volume = adev_set_master_volume;
1210 rsxadev->device.get_master_volume = adev_get_master_volume;
1211 rsxadev->device.set_master_mute = adev_set_master_mute;
1212 rsxadev->device.get_master_mute = adev_get_master_mute;
1213 rsxadev->device.set_mode = adev_set_mode;
1214 rsxadev->device.set_mic_mute = adev_set_mic_mute;
1215 rsxadev->device.get_mic_mute = adev_get_mic_mute;
1216 rsxadev->device.set_parameters = adev_set_parameters;
1217 rsxadev->device.get_parameters = adev_get_parameters;
1218 rsxadev->device.get_input_buffer_size = adev_get_input_buffer_size;
1219 rsxadev->device.open_output_stream = adev_open_output_stream;
1220 rsxadev->device.close_output_stream = adev_close_output_stream;
1221 rsxadev->device.open_input_stream = adev_open_input_stream;
1222 rsxadev->device.close_input_stream = adev_close_input_stream;
1223 rsxadev->device.dump = adev_dump;
1224
Jean-Michel Trivieec87702012-09-17 09:59:42 -07001225 rsxadev->input_standby = true;
1226 rsxadev->output_standby = true;
1227
Jean-Michel Trivi88b79cb2012-08-16 13:56:03 -07001228 *device = &rsxadev->device.common;
1229
1230 return 0;
1231}
1232
1233static struct hw_module_methods_t hal_module_methods = {
1234 /* open */ adev_open,
1235};
1236
1237struct audio_module HAL_MODULE_INFO_SYM = {
1238 /* common */ {
1239 /* tag */ HARDWARE_MODULE_TAG,
1240 /* module_api_version */ AUDIO_MODULE_API_VERSION_0_1,
1241 /* hal_api_version */ HARDWARE_HAL_API_VERSION,
1242 /* id */ AUDIO_HARDWARE_MODULE_ID,
1243 /* name */ "Wifi Display audio HAL",
1244 /* author */ "The Android Open Source Project",
1245 /* methods */ &hal_module_methods,
1246 /* dso */ NULL,
1247 /* reserved */ { 0 },
1248 },
1249};
1250
1251} //namespace android
1252
1253} //extern "C"