188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi/*
288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi * Copyright (C) 2012 The Android Open Source Project
388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi *
488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License");
588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi * you may not use this file except in compliance with the License.
688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi * You may obtain a copy of the License at
788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi *
888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi *      http://www.apache.org/licenses/LICENSE-2.0
988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi *
1088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi * Unless required by applicable law or agreed to in writing, software
1188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS,
1288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi * See the License for the specific language governing permissions and
1488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi * limitations under the License.
1588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi */
1688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
1788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi#define LOG_TAG "r_submix"
1835a2c167b4ee090b5dd9779ecb40f82cdaf1c74dJean-Michel Trivi//#define LOG_NDEBUG 0
1988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
2088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi#include <errno.h>
2188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi#include <pthread.h>
2288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi#include <stdint.h>
2388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi#include <stdlib.h>
24c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles#include <sys/param.h>
25c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles#include <sys/time.h>
26e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles#include <sys/limits.h>
2788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
2825f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi#include <cutils/compiler.h>
2988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi#include <cutils/log.h>
3088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi#include <cutils/properties.h>
31c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles#include <cutils/str_parms.h>
3288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
33c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles#include <hardware/audio.h>
3488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi#include <hardware/hardware.h>
3588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi#include <system/audio.h>
3688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
37c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles#include <media/AudioParameter.h>
38c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles#include <media/AudioBufferProvider.h>
39eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi#include <media/nbaio/MonoPipe.h>
40eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi#include <media/nbaio/MonoPipeReader.h>
4188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
42d44130339c7317faaa5cbab767eccc37347ffd25Jean-Michel Trivi#include <utils/String8.h>
43d44130339c7317faaa5cbab767eccc37347ffd25Jean-Michel Trivi
4492854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#define LOG_STREAMS_TO_FILES 0
4592854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#if LOG_STREAMS_TO_FILES
4692854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#include <fcntl.h>
4792854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#include <stdio.h>
4892854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#include <sys/stat.h>
4992854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#endif // LOG_STREAMS_TO_FILES
5092854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles
5188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Triviextern "C" {
5288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
5388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivinamespace android {
5488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
55c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles// Set to 1 to enable extremely verbose logging in this module.
56c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles#define SUBMIX_VERBOSE_LOGGING 0
57c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles#if SUBMIX_VERBOSE_LOGGING
58c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles#define SUBMIX_ALOGV(...) ALOGV(__VA_ARGS__)
59c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles#define SUBMIX_ALOGE(...) ALOGE(__VA_ARGS__)
60c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles#else
61c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles#define SUBMIX_ALOGV(...)
62c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles#define SUBMIX_ALOGE(...)
63c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles#endif // SUBMIX_VERBOSE_LOGGING
64c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles
653dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles// NOTE: This value will be rounded up to the nearest power of 2 by MonoPipe().
66bbb3e77ab0ca247c646d4a0f9d815bd6754d8ebaJean-Michel Trivi#define DEFAULT_PIPE_SIZE_IN_FRAMES  (1024*4)
673dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles// Value used to divide the MonoPipe() buffer into segments that are written to the source and
683dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles// read from the sink.  The maximum latency of the device is the size of the MonoPipe's buffer
693dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles// the minimum latency is the MonoPipe buffer size divided by this value.
703dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles#define DEFAULT_PIPE_PERIOD_COUNT    4
71eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi// The duration of MAX_READ_ATTEMPTS * READ_ATTEMPT_SLEEP_MS must be stricly inferior to
72eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi//   the duration of a record buffer at the current record sample rate (of the device, not of
73eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi//   the recording itself). Here we have:
74eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi//      3 * 5ms = 15ms < 1024 frames * 1000 / 48000 = 21.333ms
756acd966320c7f124f103044f3a152d90d6e38749Jean-Michel Trivi#define MAX_READ_ATTEMPTS            3
76eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi#define READ_ATTEMPT_SLEEP_MS        5 // 5ms between two read attempts when pipe is empty
77568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles#define DEFAULT_SAMPLE_RATE_HZ       48000 // default sample rate
78568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles// See NBAIO_Format frameworks/av/include/media/nbaio/NBAIO.h.
79568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles#define DEFAULT_FORMAT               AUDIO_FORMAT_PCM_16_BIT
803dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles// A legacy user of this device does not close the input stream when it shuts down, which
813dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles// results in the application opening a new input stream before closing the old input stream
823dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles// handle it was previously using.  Setting this value to 1 allows multiple clients to open
833dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles// multiple input streams from this device.  If this option is enabled, each input stream returned
843dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles// is *the same stream* which means that readers will race to read data from these streams.
853dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles#define ENABLE_LEGACY_INPUT_OPEN     1
86e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles// Whether channel conversion (16-bit signed PCM mono->stereo, stereo->mono) is enabled.
87e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles#define ENABLE_CHANNEL_CONVERSION    1
8802c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles// Whether resampling is enabled.
8902c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#define ENABLE_RESAMPLING            1
9092854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#if LOG_STREAMS_TO_FILES
9192854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles// Folder to save stream log files to.
92854a10af10df54eb09946d8a39c9188939d57093Eric Laurent#define LOG_STREAM_FOLDER "/data/misc/audioserver"
9392854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles// Log filenames for input and output streams.
9492854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#define LOG_STREAM_OUT_FILENAME LOG_STREAM_FOLDER "/r_submix_out.raw"
9592854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#define LOG_STREAM_IN_FILENAME LOG_STREAM_FOLDER "/r_submix_in.raw"
9692854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles// File permissions for stream log files.
9792854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#define LOG_STREAM_FILE_PERMISSIONS (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
9892854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#endif // LOG_STREAMS_TO_FILES
99793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi// limit for number of read error log entries to avoid spamming the logs
100793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi#define MAX_READ_ERROR_LOGS 5
1013dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles
1023dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles// Common limits macros.
1033dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles#ifndef min
1043dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles#define min(a, b) ((a) < (b) ? (a) : (b))
1053dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles#endif // min
106e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles#ifndef max
107e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles#define max(a, b) ((a) > (b) ? (a) : (b))
108e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles#endif // max
10988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
1107072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles// Set *result_variable_ptr to true if value_to_find is present in the array array_to_search,
1117072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles// otherwise set *result_variable_ptr to false.
1127072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles#define SUBMIX_VALUE_IN_SET(value_to_find, array_to_search, result_variable_ptr) \
1137072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    { \
1147072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles        size_t i; \
1157072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles        *(result_variable_ptr) = false; \
1167072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles        for (i = 0; i < sizeof(array_to_search) / sizeof((array_to_search)[0]); i++) { \
1177072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles          if ((value_to_find) == (array_to_search)[i]) { \
1187072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles                *(result_variable_ptr) = true; \
1197072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles                break; \
1207072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles            } \
1217072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles        } \
1227072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    }
1237072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles
124568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles// Configuration of the submix pipe.
12588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistruct submix_config {
1267072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    // Channel mask field in this data structure is set to either input_channel_mask or
1277072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    // output_channel_mask depending upon the last stream to be opened on this device.
1287072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    struct audio_config common;
1297072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    // Input stream and output stream channel masks.  This is required since input and output
1307072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    // channel bitfields are not equivalent.
1317072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    audio_channel_mask_t input_channel_mask;
1327072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    audio_channel_mask_t output_channel_mask;
13302c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#if ENABLE_RESAMPLING
13402c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles    // Input stream and output stream sample rates.
13502c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles    uint32_t input_sample_rate;
13602c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles    uint32_t output_sample_rate;
13702c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#endif // ENABLE_RESAMPLING
138e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles    size_t pipe_frame_size;  // Number of bytes in each audio frame in the pipe.
1393dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    size_t buffer_size_frames; // Size of the audio pipe in frames.
1403dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    // Maximum number of frames buffered by the input and output streams.
1413dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    size_t buffer_period_size_frames;
14288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi};
14388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
144b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi#define MAX_ROUTES 10
145b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivitypedef struct route_config {
146b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    struct submix_config config;
147b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    char address[AUDIO_DEVICE_MAX_ADDRESS_LEN];
14888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    // Pipe variables: they handle the ring buffer that "pipes" audio:
149eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi    //  - from the submix virtual audio output == what needs to be played
150eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi    //    remotely, seen as an output for AudioFlinger
15188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    //  - to the virtual audio source == what is captured by the component
15288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    //    which "records" the submix / virtual audio source, and handles it as needed.
153eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi    // A usecase example is one where the component capturing the audio is then sending it over
15488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    // Wifi for presentation on a remote Wifi Display device (e.g. a dongle attached to a TV, or a
15588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    // TV with Wifi Display capabilities), or to a wireless audio player.
156568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles    sp<MonoPipe> rsxSink;
157eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi    sp<MonoPipeReader> rsxSource;
158b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    // Pointers to the current input and output stream instances.  rsxSink and rsxSource are
159b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    // destroyed if both and input and output streams are destroyed.
160b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    struct submix_stream_out *output;
161b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    struct submix_stream_in *input;
16202c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#if ENABLE_RESAMPLING
16302c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles    // Buffer used as temporary storage for resampled data prior to returning data to the output
16402c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles    // stream.
16502c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles    int16_t resampler_buffer[DEFAULT_PIPE_SIZE_IN_FRAMES];
16602c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#endif // ENABLE_RESAMPLING
167b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi} route_config_t;
16888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
169b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivistruct submix_audio_device {
170b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    struct audio_hw_device device;
171b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    route_config_t routes[MAX_ROUTES];
172568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles    // Device lock, also used to protect access to submix_audio_device from the input and output
173568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles    // streams.
17488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    pthread_mutex_t lock;
17588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi};
17688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
17788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistruct submix_stream_out {
17888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    struct audio_stream_out stream;
17988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    struct submix_audio_device *dev;
180b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    int route_handle;
181b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    bool output_standby;
1820b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung    uint64_t frames_written;
1830b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung    uint64_t frames_written_since_standby;
18492854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#if LOG_STREAMS_TO_FILES
18592854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles    int log_fd;
18692854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#endif // LOG_STREAMS_TO_FILES
18788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi};
18888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
18988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistruct submix_stream_in {
19088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    struct audio_stream_in stream;
19188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    struct submix_audio_device *dev;
192b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    int route_handle;
193b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    bool input_standby;
194b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    bool output_standby_rec_thr; // output standby state as seen from record thread
195eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi    // wall clock when recording starts
196eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi    struct timespec record_start_time;
197eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi    // how many frames have been requested to be read
19825f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi    uint64_t read_counter_frames;
1993dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles
2003dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles#if ENABLE_LEGACY_INPUT_OPEN
2013dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    // Number of references to this input stream.
2023dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    volatile int32_t ref_count;
2033dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles#endif // ENABLE_LEGACY_INPUT_OPEN
20492854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#if LOG_STREAMS_TO_FILES
20592854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles    int log_fd;
20692854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#endif // LOG_STREAMS_TO_FILES
207793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi
208793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi    volatile int16_t read_error_count;
209eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi};
2106acd966320c7f124f103044f3a152d90d6e38749Jean-Michel Trivi
2117072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles// Determine whether the specified sample rate is supported by the submix module.
2127072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Milesstatic bool sample_rate_supported(const uint32_t sample_rate)
2137072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles{
2147072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    // Set of sample rates supported by Format_from_SR_C() frameworks/av/media/libnbaio/NAIO.cpp.
2157072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    static const unsigned int supported_sample_rates[] = {
2167072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles        8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000,
2177072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    };
2187072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    bool return_value;
2197072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    SUBMIX_VALUE_IN_SET(sample_rate, supported_sample_rates, &return_value);
2207072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    return return_value;
2217072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles}
2227072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles
2237072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles// Determine whether the specified sample rate is supported, if it is return the specified sample
2247072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles// rate, otherwise return the default sample rate for the submix module.
2257072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Milesstatic uint32_t get_supported_sample_rate(uint32_t sample_rate)
2267072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles{
2277072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles  return sample_rate_supported(sample_rate) ? sample_rate : DEFAULT_SAMPLE_RATE_HZ;
2287072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles}
2297072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles
2307072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles// Determine whether the specified channel in mask is supported by the submix module.
2317072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Milesstatic bool channel_in_mask_supported(const audio_channel_mask_t channel_in_mask)
2327072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles{
2337072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    // Set of channel in masks supported by Format_from_SR_C()
2347072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    // frameworks/av/media/libnbaio/NAIO.cpp.
2357072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    static const audio_channel_mask_t supported_channel_in_masks[] = {
2367072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles        AUDIO_CHANNEL_IN_MONO, AUDIO_CHANNEL_IN_STEREO,
2377072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    };
2387072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    bool return_value;
2397072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    SUBMIX_VALUE_IN_SET(channel_in_mask, supported_channel_in_masks, &return_value);
2407072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    return return_value;
2417072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles}
2427072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles
2437072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles// Determine whether the specified channel in mask is supported, if it is return the specified
2447072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles// channel in mask, otherwise return the default channel in mask for the submix module.
2457072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Milesstatic audio_channel_mask_t get_supported_channel_in_mask(
2467072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles        const audio_channel_mask_t channel_in_mask)
2477072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles{
2487072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    return channel_in_mask_supported(channel_in_mask) ? channel_in_mask :
2497072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles            static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_IN_STEREO);
2507072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles}
2517072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles
2527072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles// Determine whether the specified channel out mask is supported by the submix module.
2537072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Milesstatic bool channel_out_mask_supported(const audio_channel_mask_t channel_out_mask)
2547072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles{
2557072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    // Set of channel out masks supported by Format_from_SR_C()
2567072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    // frameworks/av/media/libnbaio/NAIO.cpp.
2577072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    static const audio_channel_mask_t supported_channel_out_masks[] = {
2587072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles        AUDIO_CHANNEL_OUT_MONO, AUDIO_CHANNEL_OUT_STEREO,
2597072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    };
2607072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    bool return_value;
2617072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    SUBMIX_VALUE_IN_SET(channel_out_mask, supported_channel_out_masks, &return_value);
2627072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    return return_value;
2637072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles}
2647072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles
2657072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles// Determine whether the specified channel out mask is supported, if it is return the specified
2667072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles// channel out mask, otherwise return the default channel out mask for the submix module.
2677072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Milesstatic audio_channel_mask_t get_supported_channel_out_mask(
2687072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles        const audio_channel_mask_t channel_out_mask)
2697072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles{
2707072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    return channel_out_mask_supported(channel_out_mask) ? channel_out_mask :
2717072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles        static_cast<audio_channel_mask_t>(AUDIO_CHANNEL_OUT_STEREO);
2727072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles}
2737072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles
274f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles// Get a pointer to submix_stream_out given an audio_stream_out that is embedded within the
275f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles// structure.
276f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Milesstatic struct submix_stream_out * audio_stream_out_get_submix_stream_out(
277f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles        struct audio_stream_out * const stream)
278f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles{
279f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles    ALOG_ASSERT(stream);
280f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles    return reinterpret_cast<struct submix_stream_out *>(reinterpret_cast<uint8_t *>(stream) -
281f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles                offsetof(struct submix_stream_out, stream));
282f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles}
283f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles
284f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles// Get a pointer to submix_stream_out given an audio_stream that is embedded within the structure.
285f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Milesstatic struct submix_stream_out * audio_stream_get_submix_stream_out(
286f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles        struct audio_stream * const stream)
287f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles{
288f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles    ALOG_ASSERT(stream);
289f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles    return audio_stream_out_get_submix_stream_out(
290f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles            reinterpret_cast<struct audio_stream_out *>(stream));
291f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles}
292f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles
293f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles// Get a pointer to submix_stream_in given an audio_stream_in that is embedded within the
294f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles// structure.
295f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Milesstatic struct submix_stream_in * audio_stream_in_get_submix_stream_in(
296f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles        struct audio_stream_in * const stream)
297f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles{
298f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles    ALOG_ASSERT(stream);
299f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles    return reinterpret_cast<struct submix_stream_in *>(reinterpret_cast<uint8_t *>(stream) -
300f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles            offsetof(struct submix_stream_in, stream));
301f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles}
302f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles
303f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles// Get a pointer to submix_stream_in given an audio_stream that is embedded within the structure.
304f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Milesstatic struct submix_stream_in * audio_stream_get_submix_stream_in(
305f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles        struct audio_stream * const stream)
306f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles{
307f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles    ALOG_ASSERT(stream);
308f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles    return audio_stream_in_get_submix_stream_in(
309f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles            reinterpret_cast<struct audio_stream_in *>(stream));
310f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles}
311f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles
312f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles// Get a pointer to submix_audio_device given a pointer to an audio_device that is embedded within
313f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles// the structure.
314f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Milesstatic struct submix_audio_device * audio_hw_device_get_submix_audio_device(
315f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles        struct audio_hw_device *device)
316f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles{
317f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles    ALOG_ASSERT(device);
318f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles    return reinterpret_cast<struct submix_audio_device *>(reinterpret_cast<uint8_t *>(device) -
319f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles        offsetof(struct submix_audio_device, device));
320f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles}
321f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles
3227072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles// Compare an audio_config with input channel mask and an audio_config with output channel mask
3237072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles// returning false if they do *not* match, true otherwise.
3247072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Milesstatic bool audio_config_compare(const audio_config * const input_config,
3257072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles        const audio_config * const output_config)
3267072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles{
327e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles#if !ENABLE_CHANNEL_CONVERSION
328dd45fd3aede6b116656a60a2d9b6e286d19f030fEric Laurent    const uint32_t input_channels = audio_channel_count_from_in_mask(input_config->channel_mask);
329dd45fd3aede6b116656a60a2d9b6e286d19f030fEric Laurent    const uint32_t output_channels = audio_channel_count_from_out_mask(output_config->channel_mask);
3303dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    if (input_channels != output_channels) {
3313dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        ALOGE("audio_config_compare() channel count mismatch input=%d vs. output=%d",
3323dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles              input_channels, output_channels);
3337072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles        return false;
3347072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    }
335e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles#endif // !ENABLE_CHANNEL_CONVERSION
33602c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#if ENABLE_RESAMPLING
33702c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles    if (input_config->sample_rate != output_config->sample_rate &&
338dd45fd3aede6b116656a60a2d9b6e286d19f030fEric Laurent            audio_channel_count_from_in_mask(input_config->channel_mask) != 1) {
33902c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#else
3407072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    if (input_config->sample_rate != output_config->sample_rate) {
34102c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#endif // ENABLE_RESAMPLING
3427072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles        ALOGE("audio_config_compare() sample rate mismatch %ul vs. %ul",
3437072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles              input_config->sample_rate, output_config->sample_rate);
3447072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles        return false;
3457072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    }
3467072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    if (input_config->format != output_config->format) {
3477072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles        ALOGE("audio_config_compare() format mismatch %x vs. %x",
3487072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles              input_config->format, output_config->format);
3497072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles        return false;
3507072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    }
3517072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    // This purposely ignores offload_info as it's not required for the submix device.
3527072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    return true;
3537072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles}
3547072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles
3553dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles// If one doesn't exist, create a pipe for the submix audio device rsxadev of size
3563dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles// buffer_size_frames and optionally associate "in" or "out" with the submix audio device.
357b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi// Must be called with lock held on the submix_audio_device
358b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivistatic void submix_audio_device_create_pipe_l(struct submix_audio_device * const rsxadev,
3593dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles                                            const struct audio_config * const config,
3603dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles                                            const size_t buffer_size_frames,
3613dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles                                            const uint32_t buffer_period_count,
3623dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles                                            struct submix_stream_in * const in,
363b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi                                            struct submix_stream_out * const out,
364b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi                                            const char *address,
365b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi                                            int route_idx)
3663dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles{
3673dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    ALOG_ASSERT(in || out);
368b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    ALOG_ASSERT(route_idx > -1);
369b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    ALOG_ASSERT(route_idx < MAX_ROUTES);
370b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    ALOGD("submix_audio_device_create_pipe_l(addr=%s, idx=%d)", address, route_idx);
371b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi
3723dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    // Save a reference to the specified input or output stream and the associated channel
3733dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    // mask.
3743dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    if (in) {
375b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        in->route_handle = route_idx;
376b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        rsxadev->routes[route_idx].input = in;
377b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        rsxadev->routes[route_idx].config.input_channel_mask = config->channel_mask;
37802c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#if ENABLE_RESAMPLING
379b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        rsxadev->routes[route_idx].config.input_sample_rate = config->sample_rate;
38002c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles        // If the output isn't configured yet, set the output sample rate to the maximum supported
381b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        // sample rate such that the smallest possible input buffer is created, and put a default
382b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        // value for channel count
383b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        if (!rsxadev->routes[route_idx].output) {
384b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi            rsxadev->routes[route_idx].config.output_sample_rate = 48000;
385b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi            rsxadev->routes[route_idx].config.output_channel_mask = AUDIO_CHANNEL_OUT_STEREO;
38602c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles        }
38702c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#endif // ENABLE_RESAMPLING
3883dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    }
3893dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    if (out) {
390b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        out->route_handle = route_idx;
391b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        rsxadev->routes[route_idx].output = out;
392b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        rsxadev->routes[route_idx].config.output_channel_mask = config->channel_mask;
39302c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#if ENABLE_RESAMPLING
394b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        rsxadev->routes[route_idx].config.output_sample_rate = config->sample_rate;
39502c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#endif // ENABLE_RESAMPLING
3963dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    }
397b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    // Save the address
398b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    strncpy(rsxadev->routes[route_idx].address, address, AUDIO_DEVICE_MAX_ADDRESS_LEN);
399b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    ALOGD("  now using address %s for route %d", rsxadev->routes[route_idx].address, route_idx);
4003dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    // If a pipe isn't associated with the device, create one.
401b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    if (rsxadev->routes[route_idx].rsxSink == NULL || rsxadev->routes[route_idx].rsxSource == NULL)
402b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    {
403b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        struct submix_config * const device_config = &rsxadev->routes[route_idx].config;
404dd45fd3aede6b116656a60a2d9b6e286d19f030fEric Laurent        uint32_t channel_count;
405dd45fd3aede6b116656a60a2d9b6e286d19f030fEric Laurent        if (out)
406dd45fd3aede6b116656a60a2d9b6e286d19f030fEric Laurent            channel_count = audio_channel_count_from_out_mask(config->channel_mask);
407dd45fd3aede6b116656a60a2d9b6e286d19f030fEric Laurent        else
408dd45fd3aede6b116656a60a2d9b6e286d19f030fEric Laurent            channel_count = audio_channel_count_from_in_mask(config->channel_mask);
40910f1a806e6537835de7f71dbc05db1889436732eStewart Miles#if ENABLE_CHANNEL_CONVERSION
41010f1a806e6537835de7f71dbc05db1889436732eStewart Miles        // If channel conversion is enabled, allocate enough space for the maximum number of
41110f1a806e6537835de7f71dbc05db1889436732eStewart Miles        // possible channels stored in the pipe for the situation when the number of channels in
41210f1a806e6537835de7f71dbc05db1889436732eStewart Miles        // the output stream don't match the number in the input stream.
41310f1a806e6537835de7f71dbc05db1889436732eStewart Miles        const uint32_t pipe_channel_count = max(channel_count, 2);
41410f1a806e6537835de7f71dbc05db1889436732eStewart Miles#else
41510f1a806e6537835de7f71dbc05db1889436732eStewart Miles        const uint32_t pipe_channel_count = channel_count;
41610f1a806e6537835de7f71dbc05db1889436732eStewart Miles#endif // ENABLE_CHANNEL_CONVERSION
41710f1a806e6537835de7f71dbc05db1889436732eStewart Miles        const NBAIO_Format format = Format_from_SR_C(config->sample_rate, pipe_channel_count,
41810f1a806e6537835de7f71dbc05db1889436732eStewart Miles            config->format);
4193dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        const NBAIO_Format offers[1] = {format};
4203dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        size_t numCounterOffers = 0;
4213dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        // Create a MonoPipe with optional blocking set to true.
4223dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        MonoPipe* sink = new MonoPipe(buffer_size_frames, format, true /*writeCanBlock*/);
4233dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        // Negotiation between the source and sink cannot fail as the device open operation
4243dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        // creates both ends of the pipe using the same audio format.
4253dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        ssize_t index = sink->negotiate(offers, 1, NULL, numCounterOffers);
4263dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        ALOG_ASSERT(index == 0);
4273dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        MonoPipeReader* source = new MonoPipeReader(sink);
4283dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        numCounterOffers = 0;
4293dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        index = source->negotiate(offers, 1, NULL, numCounterOffers);
4303dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        ALOG_ASSERT(index == 0);
431b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        ALOGV("submix_audio_device_create_pipe_l(): created pipe");
4323dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles
4333dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        // Save references to the source and sink.
434b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        ALOG_ASSERT(rsxadev->routes[route_idx].rsxSink == NULL);
435b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        ALOG_ASSERT(rsxadev->routes[route_idx].rsxSource == NULL);
436b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        rsxadev->routes[route_idx].rsxSink = sink;
437b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        rsxadev->routes[route_idx].rsxSource = source;
4383dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        // Store the sanitized audio format in the device so that it's possible to determine
4393dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        // the format of the pipe source when opening the input device.
4403dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        memcpy(&device_config->common, config, sizeof(device_config->common));
4413dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        device_config->buffer_size_frames = sink->maxFrames();
4423dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        device_config->buffer_period_size_frames = device_config->buffer_size_frames /
4433dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles                buffer_period_count;
444c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent        if (in) device_config->pipe_frame_size = audio_stream_in_frame_size(&in->stream);
445c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent        if (out) device_config->pipe_frame_size = audio_stream_out_frame_size(&out->stream);
44610f1a806e6537835de7f71dbc05db1889436732eStewart Miles#if ENABLE_CHANNEL_CONVERSION
44710f1a806e6537835de7f71dbc05db1889436732eStewart Miles        // Calculate the pipe frame size based upon the number of channels.
44810f1a806e6537835de7f71dbc05db1889436732eStewart Miles        device_config->pipe_frame_size = (device_config->pipe_frame_size * pipe_channel_count) /
44910f1a806e6537835de7f71dbc05db1889436732eStewart Miles                channel_count;
45010f1a806e6537835de7f71dbc05db1889436732eStewart Miles#endif // ENABLE_CHANNEL_CONVERSION
451b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        SUBMIX_ALOGV("submix_audio_device_create_pipe_l(): pipe frame size %zd, pipe size %zd, "
452e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles                     "period size %zd", device_config->pipe_frame_size,
453e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles                     device_config->buffer_size_frames, device_config->buffer_period_size_frames);
4543dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    }
4553dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles}
4563dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles
4573dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles// Release references to the sink and source.  Input and output threads may maintain references
4583dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles// to these objects via StrongPointer (sp<MonoPipe> and sp<MonoPipeReader>) which they can use
4593dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles// before they shutdown.
460b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi// Must be called with lock held on the submix_audio_device
461b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivistatic void submix_audio_device_release_pipe_l(struct submix_audio_device * const rsxadev,
462b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        int route_idx)
463b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi{
464b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    ALOG_ASSERT(route_idx > -1);
465b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    ALOG_ASSERT(route_idx < MAX_ROUTES);
466b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    ALOGD("submix_audio_device_release_pipe_l(idx=%d) addr=%s", route_idx,
467b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi            rsxadev->routes[route_idx].address);
468b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    if (rsxadev->routes[route_idx].rsxSink != 0) {
469b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        rsxadev->routes[route_idx].rsxSink.clear();
470b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        rsxadev->routes[route_idx].rsxSink = 0;
471b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    }
472b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    if (rsxadev->routes[route_idx].rsxSource != 0) {
473b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        rsxadev->routes[route_idx].rsxSource.clear();
474b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        rsxadev->routes[route_idx].rsxSource = 0;
475b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    }
476b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    memset(rsxadev->routes[route_idx].address, 0, AUDIO_DEVICE_MAX_ADDRESS_LEN);
477b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi#ifdef ENABLE_RESAMPLING
478b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    memset(rsxadev->routes[route_idx].resampler_buffer, 0,
479b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi            sizeof(int16_t) * DEFAULT_PIPE_SIZE_IN_FRAMES);
480b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi#endif
4813dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles}
4823dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles
4833dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles// Remove references to the specified input and output streams.  When the device no longer
4843dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles// references input and output streams destroy the associated pipe.
485b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi// Must be called with lock held on the submix_audio_device
486b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivistatic void submix_audio_device_destroy_pipe_l(struct submix_audio_device * const rsxadev,
4873dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles                                             const struct submix_stream_in * const in,
4883dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles                                             const struct submix_stream_out * const out)
4893dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles{
4903dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    MonoPipe* sink;
491b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    ALOGV("submix_audio_device_destroy_pipe_l()");
492b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    int route_idx = -1;
4933dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    if (in != NULL) {
4943dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles#if ENABLE_LEGACY_INPUT_OPEN
4953dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        const_cast<struct submix_stream_in*>(in)->ref_count--;
496b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        route_idx = in->route_handle;
497b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        ALOG_ASSERT(rsxadev->routes[route_idx].input == in);
4983dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        if (in->ref_count == 0) {
499b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi            rsxadev->routes[route_idx].input = NULL;
5003dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        }
501b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        ALOGV("submix_audio_device_destroy_pipe_l(): input ref_count %d", in->ref_count);
5023dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles#else
5033dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        rsxadev->input = NULL;
5043dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles#endif // ENABLE_LEGACY_INPUT_OPEN
5053dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    }
506b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    if (out != NULL) {
507b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        route_idx = out->route_handle;
508b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        ALOG_ASSERT(rsxadev->routes[route_idx].output == out);
509b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        rsxadev->routes[route_idx].output = NULL;
510b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    }
511b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    if (route_idx != -1 &&
512b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi            rsxadev->routes[route_idx].input == NULL && rsxadev->routes[route_idx].output == NULL) {
513b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        submix_audio_device_release_pipe_l(rsxadev, route_idx);
514b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        ALOGD("submix_audio_device_destroy_pipe_l(): pipe destroyed");
5153dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    }
5163dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles}
5173dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles
5187072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles// Sanitize the user specified audio config for a submix input / output stream.
5197072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Milesstatic void submix_sanitize_config(struct audio_config * const config, const bool is_input_format)
5207072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles{
5217072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    config->channel_mask = is_input_format ? get_supported_channel_in_mask(config->channel_mask) :
5227072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles            get_supported_channel_out_mask(config->channel_mask);
5237072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    config->sample_rate = get_supported_sample_rate(config->sample_rate);
5247072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    config->format = DEFAULT_FORMAT;
5257072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles}
5267072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles
5277072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles// Verify a submix input or output stream can be opened.
528b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi// Must be called with lock held on the submix_audio_device
529b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivistatic bool submix_open_validate_l(const struct submix_audio_device * const rsxadev,
530b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi                                 int route_idx,
5317072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles                                 const struct audio_config * const config,
5327072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles                                 const bool opening_input)
5337072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles{
5343dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    bool input_open;
5353dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    bool output_open;
5367072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    audio_config pipe_config;
5377072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles
5387072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    // Query the device for the current audio config and whether input and output streams are open.
539b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    output_open = rsxadev->routes[route_idx].output != NULL;
540b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    input_open = rsxadev->routes[route_idx].input != NULL;
541b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    memcpy(&pipe_config, &rsxadev->routes[route_idx].config.common, sizeof(pipe_config));
5427072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles
5433dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    // If the stream is already open, don't open it again.
5443dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    if (opening_input ? !ENABLE_LEGACY_INPUT_OPEN && input_open : output_open) {
545b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        ALOGE("submix_open_validate_l(): %s stream already open.", opening_input ? "Input" :
5463dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles                "Output");
5473dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        return false;
5483dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    }
5493dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles
550b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    SUBMIX_ALOGV("submix_open_validate_l(): sample rate=%d format=%x "
5513dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles                 "%s_channel_mask=%x", config->sample_rate, config->format,
5523dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles                 opening_input ? "in" : "out", config->channel_mask);
5533dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles
5543dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    // If either stream is open, verify the existing audio config the pipe matches the user
5557072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    // specified config.
5563dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    if (input_open || output_open) {
5577072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles        const audio_config * const input_config = opening_input ? config : &pipe_config;
5587072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles        const audio_config * const output_config = opening_input ? &pipe_config : config;
5597072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles        // Get the channel mask of the open device.
5607072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles        pipe_config.channel_mask =
561b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi            opening_input ? rsxadev->routes[route_idx].config.output_channel_mask :
562b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi                rsxadev->routes[route_idx].config.input_channel_mask;
5637072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles        if (!audio_config_compare(input_config, output_config)) {
564b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi            ALOGE("submix_open_validate_l(): Unsupported format.");
5653dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles            return false;
5667072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles        }
5677072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    }
5687072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    return true;
5697072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles}
5707072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles
571b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi// Must be called with lock held on the submix_audio_device
572b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivistatic status_t submix_get_route_idx_for_address_l(const struct submix_audio_device * const rsxadev,
573b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi                                                 const char* address, /*in*/
574b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi                                                 int *idx /*out*/)
575b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi{
576b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    // Do we already have a route for this address
577b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    int route_idx = -1;
578b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    int route_empty_idx = -1; // index of an empty route slot that can be used if needed
579b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    for (int i=0 ; i < MAX_ROUTES ; i++) {
580b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        if (strcmp(rsxadev->routes[i].address, "") == 0) {
581b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi            route_empty_idx = i;
582b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        }
583b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        if (strncmp(rsxadev->routes[i].address, address, AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0) {
584b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi            route_idx = i;
585b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi            break;
586b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        }
587b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    }
588b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi
589b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    if ((route_idx == -1) && (route_empty_idx == -1)) {
590b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        ALOGE("Cannot create new route for address %s, max number of routes reached", address);
591b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        return -ENOMEM;
592b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    }
593b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    if (route_idx == -1) {
594b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        route_idx = route_empty_idx;
595b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    }
596b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    *idx = route_idx;
597b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    return OK;
598b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi}
599b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi
600b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi
601e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles// Calculate the maximum size of the pipe buffer in frames for the specified stream.
602e54c12cd532dc36286d500c03ad638402254d4e5Stewart Milesstatic size_t calculate_stream_pipe_size_in_frames(const struct audio_stream *stream,
603e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles                                                   const struct submix_config *config,
604c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent                                                   const size_t pipe_frames,
605c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent                                                   const size_t stream_frame_size)
606e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles{
607e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles    const size_t pipe_frame_size = config->pipe_frame_size;
608e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles    const size_t max_frame_size = max(stream_frame_size, pipe_frame_size);
609e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles    return (pipe_frames * config->pipe_frame_size) / max_frame_size;
610e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles}
611e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles
61288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi/* audio HAL functions */
61388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
61488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic uint32_t out_get_sample_rate(const struct audio_stream *stream)
61588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
616f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles    const struct submix_stream_out * const out = audio_stream_get_submix_stream_out(
617f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles            const_cast<struct audio_stream *>(stream));
61802c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#if ENABLE_RESAMPLING
619b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    const uint32_t out_rate = out->dev->routes[out->route_handle].config.output_sample_rate;
62002c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#else
621b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    const uint32_t out_rate = out->dev->routes[out->route_handle].config.common.sample_rate;
62202c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#endif // ENABLE_RESAMPLING
623b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    SUBMIX_ALOGV("out_get_sample_rate() returns %u for addr %s",
624b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi            out_rate, out->dev->routes[out->route_handle].address);
62588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    return out_rate;
62688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
62788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
62888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
62988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
63002c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles    struct submix_stream_out * const out = audio_stream_get_submix_stream_out(stream);
63102c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#if ENABLE_RESAMPLING
63202c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles    // The sample rate of the stream can't be changed once it's set since this would change the
63302c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles    // output buffer size and hence break playback to the shared pipe.
634b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    if (rate != out->dev->routes[out->route_handle].config.output_sample_rate) {
635c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent        ALOGE("out_set_sample_rate() resampling enabled can't change sample rate from "
636b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi              "%u to %u for addr %s",
637b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi              out->dev->routes[out->route_handle].config.output_sample_rate, rate,
638b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi              out->dev->routes[out->route_handle].address);
63902c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles        return -ENOSYS;
64002c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles    }
64102c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#endif // ENABLE_RESAMPLING
6427072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    if (!sample_rate_supported(rate)) {
64388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi        ALOGE("out_set_sample_rate(rate=%u) rate unsupported", rate);
64488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi        return -ENOSYS;
64588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    }
646c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    SUBMIX_ALOGV("out_set_sample_rate(rate=%u)", rate);
647b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    out->dev->routes[out->route_handle].config.common.sample_rate = rate;
64888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    return 0;
64988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
65088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
65188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic size_t out_get_buffer_size(const struct audio_stream *stream)
65288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
653f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles    const struct submix_stream_out * const out = audio_stream_get_submix_stream_out(
654f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles            const_cast<struct audio_stream *>(stream));
655b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    const struct submix_config * const config = &out->dev->routes[out->route_handle].config;
656c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent    const size_t stream_frame_size =
657c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent                            audio_stream_out_frame_size((const struct audio_stream_out *)stream);
658e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles    const size_t buffer_size_frames = calculate_stream_pipe_size_in_frames(
659c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent        stream, config, config->buffer_period_size_frames, stream_frame_size);
660c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent    const size_t buffer_size_bytes = buffer_size_frames * stream_frame_size;
661568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles    SUBMIX_ALOGV("out_get_buffer_size() returns %zu bytes, %zu frames",
662e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles                 buffer_size_bytes, buffer_size_frames);
663e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles    return buffer_size_bytes;
66488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
66588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
66688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic audio_channel_mask_t out_get_channels(const struct audio_stream *stream)
66788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
668f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles    const struct submix_stream_out * const out = audio_stream_get_submix_stream_out(
669f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles            const_cast<struct audio_stream *>(stream));
670b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    uint32_t channel_mask = out->dev->routes[out->route_handle].config.output_channel_mask;
671568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles    SUBMIX_ALOGV("out_get_channels() returns %08x", channel_mask);
672568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles    return channel_mask;
67388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
67488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
67588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic audio_format_t out_get_format(const struct audio_stream *stream)
67688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
677568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles    const struct submix_stream_out * const out = audio_stream_get_submix_stream_out(
678568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles            const_cast<struct audio_stream *>(stream));
679b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    const audio_format_t format = out->dev->routes[out->route_handle].config.common.format;
680568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles    SUBMIX_ALOGV("out_get_format() returns %x", format);
681568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles    return format;
68288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
68388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
68488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int out_set_format(struct audio_stream *stream, audio_format_t format)
68588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
686568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles    const struct submix_stream_out * const out = audio_stream_get_submix_stream_out(stream);
687b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    if (format != out->dev->routes[out->route_handle].config.common.format) {
688c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles        ALOGE("out_set_format(format=%x) format unsupported", format);
68988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi        return -ENOSYS;
69088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    }
691c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    SUBMIX_ALOGV("out_set_format(format=%x)", format);
692c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    return 0;
69388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
69488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
69588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int out_standby(struct audio_stream *stream)
69688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
697eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi    ALOGI("out_standby()");
698b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    struct submix_stream_out * const out = audio_stream_get_submix_stream_out(stream);
699b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    struct submix_audio_device * const rsxadev = out->dev;
700eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi
701f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles    pthread_mutex_lock(&rsxadev->lock);
702eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi
703b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    out->output_standby = true;
7040b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung    out->frames_written_since_standby = 0;
705eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi
706f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles    pthread_mutex_unlock(&rsxadev->lock);
707eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi
70888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    return 0;
70988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
71088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
71188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int out_dump(const struct audio_stream *stream, int fd)
71288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
713c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)stream;
714c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)fd;
71588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    return 0;
71688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
71788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
71888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
71988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
720d44130339c7317faaa5cbab767eccc37347ffd25Jean-Michel Trivi    int exiting = -1;
721d44130339c7317faaa5cbab767eccc37347ffd25Jean-Michel Trivi    AudioParameter parms = AudioParameter(String8(kvpairs));
722c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    SUBMIX_ALOGV("out_set_parameters() kvpairs='%s'", kvpairs);
7233dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles
724d44130339c7317faaa5cbab767eccc37347ffd25Jean-Michel Trivi    // FIXME this is using hard-coded strings but in the future, this functionality will be
725d44130339c7317faaa5cbab767eccc37347ffd25Jean-Michel Trivi    //       converted to use audio HAL extensions required to support tunneling
726d44130339c7317faaa5cbab767eccc37347ffd25Jean-Michel Trivi    if ((parms.getInt(String8("exiting"), exiting) == NO_ERROR) && (exiting > 0)) {
727f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles        struct submix_audio_device * const rsxadev =
728f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles                audio_stream_get_submix_stream_out(stream)->dev;
729f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles        pthread_mutex_lock(&rsxadev->lock);
730eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi        { // using the sink
731b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi            sp<MonoPipe> sink =
732b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi                    rsxadev->routes[audio_stream_get_submix_stream_out(stream)->route_handle]
733b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi                                    .rsxSink;
734f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles            if (sink == NULL) {
735f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles                pthread_mutex_unlock(&rsxadev->lock);
736eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi                return 0;
737eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi            }
738d44130339c7317faaa5cbab767eccc37347ffd25Jean-Michel Trivi
739793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi            ALOGD("out_set_parameters(): shutting down MonoPipe sink");
740eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi            sink->shutdown(true);
741eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi        } // done using the sink
742f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles        pthread_mutex_unlock(&rsxadev->lock);
743d44130339c7317faaa5cbab767eccc37347ffd25Jean-Michel Trivi    }
74488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    return 0;
74588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
74688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
74788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic char * out_get_parameters(const struct audio_stream *stream, const char *keys)
74888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
749c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)stream;
750c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)keys;
75188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    return strdup("");
75288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
75388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
75488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic uint32_t out_get_latency(const struct audio_stream_out *stream)
75588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
756f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles    const struct submix_stream_out * const out = audio_stream_out_get_submix_stream_out(
757f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles            const_cast<struct audio_stream_out *>(stream));
758b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    const struct submix_config * const config = &out->dev->routes[out->route_handle].config;
759c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent    const size_t stream_frame_size =
760c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent                            audio_stream_out_frame_size(stream);
761e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles    const size_t buffer_size_frames = calculate_stream_pipe_size_in_frames(
762c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent            &stream->common, config, config->buffer_size_frames, stream_frame_size);
76310f1a806e6537835de7f71dbc05db1889436732eStewart Miles    const uint32_t sample_rate = out_get_sample_rate(&stream->common);
76410f1a806e6537835de7f71dbc05db1889436732eStewart Miles    const uint32_t latency_ms = (buffer_size_frames * 1000) / sample_rate;
765e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles    SUBMIX_ALOGV("out_get_latency() returns %u ms, size in frames %zu, sample rate %u",
76610f1a806e6537835de7f71dbc05db1889436732eStewart Miles                 latency_ms, buffer_size_frames, sample_rate);
767568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles    return latency_ms;
76888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
76988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
77088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int out_set_volume(struct audio_stream_out *stream, float left,
77188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi                          float right)
77288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
773c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)stream;
774c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)left;
775c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)right;
77688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    return -ENOSYS;
77788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
77888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
77988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
78088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi                         size_t bytes)
78188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
782c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    SUBMIX_ALOGV("out_write(bytes=%zd)", bytes);
783eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi    ssize_t written_frames = 0;
784c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent    const size_t frame_size = audio_stream_out_frame_size(stream);
7853dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    struct submix_stream_out * const out = audio_stream_out_get_submix_stream_out(stream);
7863dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    struct submix_audio_device * const rsxadev = out->dev;
78790b0fbd13f97127e29ea565c09b64cc25ab6e9c9Jean-Michel Trivi    const size_t frames = bytes / frame_size;
78890b0fbd13f97127e29ea565c09b64cc25ab6e9c9Jean-Michel Trivi
789f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles    pthread_mutex_lock(&rsxadev->lock);
79088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
791b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    out->output_standby = false;
792eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi
793b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    sp<MonoPipe> sink = rsxadev->routes[out->route_handle].rsxSink;
794f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles    if (sink != NULL) {
79590b0fbd13f97127e29ea565c09b64cc25ab6e9c9Jean-Michel Trivi        if (sink->isShutdown()) {
796eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi            sink.clear();
797f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles            pthread_mutex_unlock(&rsxadev->lock);
798c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles            SUBMIX_ALOGV("out_write(): pipe shutdown, ignoring the write.");
79990b0fbd13f97127e29ea565c09b64cc25ab6e9c9Jean-Michel Trivi            // the pipe has already been shutdown, this buffer will be lost but we must
80090b0fbd13f97127e29ea565c09b64cc25ab6e9c9Jean-Michel Trivi            //   simulate timing so we don't drain the output faster than realtime
80190b0fbd13f97127e29ea565c09b64cc25ab6e9c9Jean-Michel Trivi            usleep(frames * 1000000 / out_get_sample_rate(&stream->common));
80290b0fbd13f97127e29ea565c09b64cc25ab6e9c9Jean-Michel Trivi            return bytes;
80390b0fbd13f97127e29ea565c09b64cc25ab6e9c9Jean-Michel Trivi        }
80488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    } else {
805f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles        pthread_mutex_unlock(&rsxadev->lock);
80688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi        ALOGE("out_write without a pipe!");
80788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi        ALOG_ASSERT("out_write without a pipe!");
80888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi        return 0;
80988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    }
81088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
8112d199fe082312963edd1ac198197280a4f18ca21Stewart Miles    // If the write to the sink would block when no input stream is present, flush enough frames
8122d199fe082312963edd1ac198197280a4f18ca21Stewart Miles    // from the pipe to make space to write the most recent data.
8132d199fe082312963edd1ac198197280a4f18ca21Stewart Miles    {
8142d199fe082312963edd1ac198197280a4f18ca21Stewart Miles        const size_t availableToWrite = sink->availableToWrite();
815b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        sp<MonoPipeReader> source = rsxadev->routes[out->route_handle].rsxSource;
816b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        if (rsxadev->routes[out->route_handle].input == NULL && availableToWrite < frames) {
8172d199fe082312963edd1ac198197280a4f18ca21Stewart Miles            static uint8_t flush_buffer[64];
8182d199fe082312963edd1ac198197280a4f18ca21Stewart Miles            const size_t flushBufferSizeFrames = sizeof(flush_buffer) / frame_size;
8192d199fe082312963edd1ac198197280a4f18ca21Stewart Miles            size_t frames_to_flush_from_source = frames - availableToWrite;
8202d199fe082312963edd1ac198197280a4f18ca21Stewart Miles            SUBMIX_ALOGV("out_write(): flushing %d frames from the pipe to avoid blocking",
8212d199fe082312963edd1ac198197280a4f18ca21Stewart Miles                         frames_to_flush_from_source);
8222d199fe082312963edd1ac198197280a4f18ca21Stewart Miles            while (frames_to_flush_from_source) {
8232d199fe082312963edd1ac198197280a4f18ca21Stewart Miles                const size_t flush_size = min(frames_to_flush_from_source, flushBufferSizeFrames);
8242d199fe082312963edd1ac198197280a4f18ca21Stewart Miles                frames_to_flush_from_source -= flush_size;
825b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi                // read does not block
82604c88495bb7caf851f9802dee20a2a1ffceff195Glenn Kasten                source->read(flush_buffer, flush_size);
8272d199fe082312963edd1ac198197280a4f18ca21Stewart Miles            }
8282d199fe082312963edd1ac198197280a4f18ca21Stewart Miles        }
8292d199fe082312963edd1ac198197280a4f18ca21Stewart Miles    }
8302d199fe082312963edd1ac198197280a4f18ca21Stewart Miles
831f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles    pthread_mutex_unlock(&rsxadev->lock);
83288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
833eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi    written_frames = sink->write(buffer, frames);
834eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi
83592854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#if LOG_STREAMS_TO_FILES
83692854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles    if (out->log_fd >= 0) write(out->log_fd, buffer, written_frames * frame_size);
83792854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#endif // LOG_STREAMS_TO_FILES
83892854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles
839eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi    if (written_frames < 0) {
840eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi        if (written_frames == (ssize_t)NEGOTIATE) {
84188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi            ALOGE("out_write() write to pipe returned NEGOTIATE");
842eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi
843f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles            pthread_mutex_lock(&rsxadev->lock);
844eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi            sink.clear();
845f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles            pthread_mutex_unlock(&rsxadev->lock);
846eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi
847eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi            written_frames = 0;
8486acd966320c7f124f103044f3a152d90d6e38749Jean-Michel Trivi            return 0;
84988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi        } else {
85088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi            // write() returned UNDERRUN or WOULD_BLOCK, retry
8515685a0845ecde4a1e53684473af3de77e6641af6Colin Cross            ALOGE("out_write() write to pipe returned unexpected %zd", written_frames);
852eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi            written_frames = sink->write(buffer, frames);
85388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi        }
85488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    }
85588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
856f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles    pthread_mutex_lock(&rsxadev->lock);
857eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi    sink.clear();
85825f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi    if (written_frames > 0) {
8590b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung        out->frames_written_since_standby += written_frames;
8600b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung        out->frames_written += written_frames;
86125f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi    }
862f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles    pthread_mutex_unlock(&rsxadev->lock);
86388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
864eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi    if (written_frames < 0) {
8655685a0845ecde4a1e53684473af3de77e6641af6Colin Cross        ALOGE("out_write() failed writing to pipe with %zd", written_frames);
866eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi        return 0;
86788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    }
868c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    const ssize_t written_bytes = written_frames * frame_size;
86902c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles    SUBMIX_ALOGV("out_write() wrote %zd bytes %zd frames", written_bytes, written_frames);
870c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    return written_bytes;
87188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
87288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
87325f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivistatic int out_get_presentation_position(const struct audio_stream_out *stream,
87425f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi                                   uint64_t *frames, struct timespec *timestamp)
87525f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi{
8760b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung    if (stream == NULL || frames == NULL || timestamp == NULL) {
8770b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung        return -EINVAL;
8780b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung    }
8790b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung
8800b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung    const submix_stream_out *out = audio_stream_out_get_submix_stream_out(
8810b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung            const_cast<struct audio_stream_out *>(stream));
88225f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi    struct submix_audio_device * const rsxadev = out->dev;
88325f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi
8840b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung    int ret = -EWOULDBLOCK;
88525f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi    pthread_mutex_lock(&rsxadev->lock);
8860b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung    const ssize_t frames_in_pipe =
8870b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung            rsxadev->routes[out->route_handle].rsxSource->availableToRead();
8880b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung    if (CC_UNLIKELY(frames_in_pipe < 0)) {
8890b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung        *frames = out->frames_written;
8900b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung        ret = 0;
8910b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung    } else if (out->frames_written >= (uint64_t)frames_in_pipe) {
8920b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung        *frames = out->frames_written - frames_in_pipe;
8930b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung        ret = 0;
89425f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi    }
8950b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung    pthread_mutex_unlock(&rsxadev->lock);
8960b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung
8970b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung    if (ret == 0) {
89825f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi        clock_gettime(CLOCK_MONOTONIC, timestamp);
89925f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi    }
90025f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi
90125f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi    SUBMIX_ALOGV("out_get_presentation_position() got frames=%llu timestamp sec=%llu",
90225f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi            frames ? *frames : -1, timestamp ? timestamp->tv_sec : -1);
90325f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi
90425f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi    return ret;
90525f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi}
90625f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi
90788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int out_get_render_position(const struct audio_stream_out *stream,
90888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi                                   uint32_t *dsp_frames)
90988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
9100b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung    if (stream == NULL || dsp_frames == NULL) {
91125f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi        return -EINVAL;
91225f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi    }
9130b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung
9140b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung    const submix_stream_out *out = audio_stream_out_get_submix_stream_out(
9150b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung            const_cast<struct audio_stream_out *>(stream));
9160b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung    struct submix_audio_device * const rsxadev = out->dev;
9170b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung
9180b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung    pthread_mutex_lock(&rsxadev->lock);
9190b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung    const ssize_t frames_in_pipe =
9200b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung            rsxadev->routes[out->route_handle].rsxSource->availableToRead();
9210b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung    if (CC_UNLIKELY(frames_in_pipe < 0)) {
9220b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung        *dsp_frames = (uint32_t)out->frames_written_since_standby;
9230b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung    } else {
9240b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung        *dsp_frames = out->frames_written_since_standby > (uint64_t) frames_in_pipe ?
9250b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung                (uint32_t)(out->frames_written_since_standby - frames_in_pipe) : 0;
92625f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi    }
9270b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung    pthread_mutex_unlock(&rsxadev->lock);
9280b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung
9290b93c0ab58a9d919d13c3d25f2ba262df0082519Andy Hung    return 0;
93088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
93188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
93288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
93388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
934c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)stream;
935c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)effect;
93688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    return 0;
93788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
93888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
93988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
94088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
941c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)stream;
942c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)effect;
94388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    return 0;
94488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
94588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
94688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int out_get_next_write_timestamp(const struct audio_stream_out *stream,
94788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi                                        int64_t *timestamp)
94888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
949c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)stream;
950c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)timestamp;
95188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    return -EINVAL;
95288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
95388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
95488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi/** audio_stream_in implementation **/
95588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic uint32_t in_get_sample_rate(const struct audio_stream *stream)
95688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
957f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles    const struct submix_stream_in * const in = audio_stream_get_submix_stream_in(
958f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles        const_cast<struct audio_stream*>(stream));
95902c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#if ENABLE_RESAMPLING
960b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    const uint32_t rate = in->dev->routes[in->route_handle].config.input_sample_rate;
96102c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#else
962b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    const uint32_t rate = in->dev->routes[in->route_handle].config.common.sample_rate;
96302c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#endif // ENABLE_RESAMPLING
96402c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles    SUBMIX_ALOGV("in_get_sample_rate() returns %u", rate);
96502c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles    return rate;
96688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
96788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
96888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
96988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
970568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles    const struct submix_stream_in * const in = audio_stream_get_submix_stream_in(stream);
97102c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#if ENABLE_RESAMPLING
97202c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles    // The sample rate of the stream can't be changed once it's set since this would change the
97302c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles    // input buffer size and hence break recording from the shared pipe.
974b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    if (rate != in->dev->routes[in->route_handle].config.input_sample_rate) {
975c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent        ALOGE("in_set_sample_rate() resampling enabled can't change sample rate from "
976b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi              "%u to %u", in->dev->routes[in->route_handle].config.input_sample_rate, rate);
97702c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles        return -ENOSYS;
97802c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles    }
97902c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#endif // ENABLE_RESAMPLING
9807072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    if (!sample_rate_supported(rate)) {
9817072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles        ALOGE("in_set_sample_rate(rate=%u) rate unsupported", rate);
9827072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles        return -ENOSYS;
9837072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    }
984b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    in->dev->routes[in->route_handle].config.common.sample_rate = rate;
985568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles    SUBMIX_ALOGV("in_set_sample_rate() set %u", rate);
986568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles    return 0;
98788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
98888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
98988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic size_t in_get_buffer_size(const struct audio_stream *stream)
99088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
991f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles    const struct submix_stream_in * const in = audio_stream_get_submix_stream_in(
992f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles            const_cast<struct audio_stream*>(stream));
993b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    const struct submix_config * const config = &in->dev->routes[in->route_handle].config;
994c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent    const size_t stream_frame_size =
995c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent                            audio_stream_in_frame_size((const struct audio_stream_in *)stream);
99602c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles    size_t buffer_size_frames = calculate_stream_pipe_size_in_frames(
997c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent        stream, config, config->buffer_period_size_frames, stream_frame_size);
99802c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#if ENABLE_RESAMPLING
99902c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles    // Scale the size of the buffer based upon the maximum number of frames that could be returned
100002c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles    // given the ratio of output to input sample rate.
100102c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles    buffer_size_frames = (size_t)(((float)buffer_size_frames *
100202c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles                                   (float)config->input_sample_rate) /
100302c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles                                  (float)config->output_sample_rate);
100402c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#endif // ENABLE_RESAMPLING
1005c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent    const size_t buffer_size_bytes = buffer_size_frames * stream_frame_size;
1006e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles    SUBMIX_ALOGV("in_get_buffer_size() returns %zu bytes, %zu frames", buffer_size_bytes,
1007e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles                 buffer_size_frames);
1008e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles    return buffer_size_bytes;
100988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
101088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
101188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic audio_channel_mask_t in_get_channels(const struct audio_stream *stream)
101288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
10137072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    const struct submix_stream_in * const in = audio_stream_get_submix_stream_in(
10147072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles            const_cast<struct audio_stream*>(stream));
1015b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    const audio_channel_mask_t channel_mask =
1016b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi            in->dev->routes[in->route_handle].config.input_channel_mask;
10177072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    SUBMIX_ALOGV("in_get_channels() returns %x", channel_mask);
10187072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    return channel_mask;
101988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
102088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
102188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic audio_format_t in_get_format(const struct audio_stream *stream)
102288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
1023568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles    const struct submix_stream_in * const in = audio_stream_get_submix_stream_in(
10247072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles            const_cast<struct audio_stream*>(stream));
1025b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    const audio_format_t format = in->dev->routes[in->route_handle].config.common.format;
1026568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles    SUBMIX_ALOGV("in_get_format() returns %x", format);
1027568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles    return format;
102888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
102988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
103088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int in_set_format(struct audio_stream *stream, audio_format_t format)
103188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
1032568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles    const struct submix_stream_in * const in = audio_stream_get_submix_stream_in(stream);
1033b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    if (format != in->dev->routes[in->route_handle].config.common.format) {
1034c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles        ALOGE("in_set_format(format=%x) format unsupported", format);
103588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi        return -ENOSYS;
103688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    }
1037c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    SUBMIX_ALOGV("in_set_format(format=%x)", format);
1038c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    return 0;
103988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
104088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
104188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int in_standby(struct audio_stream *stream)
104288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
1043eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi    ALOGI("in_standby()");
1044b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    struct submix_stream_in * const in = audio_stream_get_submix_stream_in(stream);
1045b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    struct submix_audio_device * const rsxadev = in->dev;
1046eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi
1047f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles    pthread_mutex_lock(&rsxadev->lock);
1048eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi
1049b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    in->input_standby = true;
1050eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi
1051f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles    pthread_mutex_unlock(&rsxadev->lock);
1052eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi
105388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    return 0;
105488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
105588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
105688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int in_dump(const struct audio_stream *stream, int fd)
105788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
1058c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)stream;
1059c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)fd;
106088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    return 0;
106188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
106288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
106388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
106488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
1065c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)stream;
1066c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)kvpairs;
106788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    return 0;
106888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
106988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
107088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic char * in_get_parameters(const struct audio_stream *stream,
107188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi                                const char *keys)
107288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
1073c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)stream;
1074c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)keys;
107588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    return strdup("");
107688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
107788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
107888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int in_set_gain(struct audio_stream_in *stream, float gain)
107988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
1080c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)stream;
1081c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)gain;
108288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    return 0;
108388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
108488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
108588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic ssize_t in_read(struct audio_stream_in *stream, void* buffer,
108688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi                       size_t bytes)
108788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
1088f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles    struct submix_stream_in * const in = audio_stream_in_get_submix_stream_in(stream);
1089f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles    struct submix_audio_device * const rsxadev = in->dev;
1090e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles    struct audio_config *format;
1091c5ae6a030484f83beb3f2120f136cec1c0ef8b0aEric Laurent    const size_t frame_size = audio_stream_in_frame_size(stream);
1092eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi    const size_t frames_to_read = bytes / frame_size;
109388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
1094c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    SUBMIX_ALOGV("in_read bytes=%zu", bytes);
1095f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles    pthread_mutex_lock(&rsxadev->lock);
109688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
1097257fde6eb533b890776c8c45be8b61c48ab04945Jean-Michel Trivi    const bool output_standby = rsxadev->routes[in->route_handle].output == NULL
1098257fde6eb533b890776c8c45be8b61c48ab04945Jean-Michel Trivi            ? true : rsxadev->routes[in->route_handle].output->output_standby;
1099257fde6eb533b890776c8c45be8b61c48ab04945Jean-Michel Trivi    const bool output_standby_transition = (in->output_standby_rec_thr != output_standby);
1100257fde6eb533b890776c8c45be8b61c48ab04945Jean-Michel Trivi    in->output_standby_rec_thr = output_standby;
1101eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi
1102b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    if (in->input_standby || output_standby_transition) {
1103b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        in->input_standby = false;
1104eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi        // keep track of when we exit input standby (== first read == start "real recording")
1105eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi        // or when we start recording silence, and reset projected time
1106eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi        int rc = clock_gettime(CLOCK_MONOTONIC, &in->record_start_time);
1107eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi        if (rc == 0) {
1108eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi            in->read_counter_frames = 0;
1109eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi        }
1110eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi    }
1111eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi
1112eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi    in->read_counter_frames += frames_to_read;
1113eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi    size_t remaining_frames = frames_to_read;
1114eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi
1115eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi    {
1116eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi        // about to read from audio source
1117b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        sp<MonoPipeReader> source = rsxadev->routes[in->route_handle].rsxSource;
1118f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles        if (source == NULL) {
1119793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi            in->read_error_count++;// ok if it rolls over
1120793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi            ALOGE_IF(in->read_error_count < MAX_READ_ERROR_LOGS,
1121793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi                    "no audio pipe yet we're trying to read! (not all errors will be logged)");
1122f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles            pthread_mutex_unlock(&rsxadev->lock);
11233dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles            usleep(frames_to_read * 1000000 / in_get_sample_rate(&stream->common));
1124eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi            memset(buffer, 0, bytes);
1125eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi            return bytes;
1126eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi        }
112788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
1128f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles        pthread_mutex_unlock(&rsxadev->lock);
112988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
1130eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi        // read the data from the pipe (it's non blocking)
1131eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi        int attempts = 0;
1132eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi        char* buff = (char*)buffer;
1133e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles#if ENABLE_CHANNEL_CONVERSION
1134e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles        // Determine whether channel conversion is required.
1135dd45fd3aede6b116656a60a2d9b6e286d19f030fEric Laurent        const uint32_t input_channels = audio_channel_count_from_in_mask(
1136b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi            rsxadev->routes[in->route_handle].config.input_channel_mask);
1137dd45fd3aede6b116656a60a2d9b6e286d19f030fEric Laurent        const uint32_t output_channels = audio_channel_count_from_out_mask(
1138b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi            rsxadev->routes[in->route_handle].config.output_channel_mask);
1139e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles        if (input_channels != output_channels) {
1140e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles            SUBMIX_ALOGV("in_read(): %d output channels will be converted to %d "
1141e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles                         "input channels", output_channels, input_channels);
1142e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles            // Only support 16-bit PCM channel conversion from mono to stereo or stereo to mono.
1143b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi            ALOG_ASSERT(rsxadev->routes[in->route_handle].config.common.format ==
1144b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi                    AUDIO_FORMAT_PCM_16_BIT);
1145e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles            ALOG_ASSERT((input_channels == 1 && output_channels == 2) ||
1146e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles                        (input_channels == 2 && output_channels == 1));
1147e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles        }
1148e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles#endif // ENABLE_CHANNEL_CONVERSION
1149e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles
115002c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#if ENABLE_RESAMPLING
115102c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles        const uint32_t input_sample_rate = in_get_sample_rate(&stream->common);
1152b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        const uint32_t output_sample_rate =
1153b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi                rsxadev->routes[in->route_handle].config.output_sample_rate;
115402c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles        const size_t resampler_buffer_size_frames =
1155b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi            sizeof(rsxadev->routes[in->route_handle].resampler_buffer) /
1156b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi                sizeof(rsxadev->routes[in->route_handle].resampler_buffer[0]);
115702c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles        float resampler_ratio = 1.0f;
115802c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles        // Determine whether resampling is required.
115902c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles        if (input_sample_rate != output_sample_rate) {
116002c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles            resampler_ratio = (float)output_sample_rate / (float)input_sample_rate;
116102c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles            // Only support 16-bit PCM mono resampling.
116202c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles            // NOTE: Resampling is performed after the channel conversion step.
1163b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi            ALOG_ASSERT(rsxadev->routes[in->route_handle].config.common.format ==
1164b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi                    AUDIO_FORMAT_PCM_16_BIT);
1165b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi            ALOG_ASSERT(audio_channel_count_from_in_mask(
1166b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi                    rsxadev->routes[in->route_handle].config.input_channel_mask) == 1);
116702c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles        }
116802c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#endif // ENABLE_RESAMPLING
116902c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles
1170eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi        while ((remaining_frames > 0) && (attempts < MAX_READ_ATTEMPTS)) {
117102c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles            ssize_t frames_read = -1977;
1172e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles            size_t read_frames = remaining_frames;
117302c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#if ENABLE_RESAMPLING
117402c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles            char* const saved_buff = buff;
117502c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles            if (resampler_ratio != 1.0f) {
117602c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles                // Calculate the number of frames from the pipe that need to be read to generate
117702c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles                // the data for the input stream read.
117802c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles                const size_t frames_required_for_resampler = (size_t)(
117902c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles                    (float)read_frames * (float)resampler_ratio);
118002c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles                read_frames = min(frames_required_for_resampler, resampler_buffer_size_frames);
118102c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles                // Read into the resampler buffer.
1182b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi                buff = (char*)rsxadev->routes[in->route_handle].resampler_buffer;
118302c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles            }
118402c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#endif // ENABLE_RESAMPLING
1185e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles#if ENABLE_CHANNEL_CONVERSION
1186e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles            if (output_channels == 1 && input_channels == 2) {
1187e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles                // Need to read half the requested frames since the converted output
1188e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles                // data will take twice the space (mono->stereo).
1189e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles                read_frames /= 2;
1190e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles            }
1191e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles#endif // ENABLE_CHANNEL_CONVERSION
1192e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles
1193e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles            SUBMIX_ALOGV("in_read(): frames available to read %zd", source->availableToRead());
1194e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles
119504c88495bb7caf851f9802dee20a2a1ffceff195Glenn Kasten            frames_read = source->read(buff, read_frames);
1196e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles
1197e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles            SUBMIX_ALOGV("in_read(): frames read %zd", frames_read);
1198e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles
1199e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles#if ENABLE_CHANNEL_CONVERSION
1200e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles            // Perform in-place channel conversion.
1201e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles            // NOTE: In the following "input stream" refers to the data returned by this function
1202e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles            // and "output stream" refers to the data read from the pipe.
1203e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles            if (input_channels != output_channels && frames_read > 0) {
1204e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles                int16_t *data = (int16_t*)buff;
1205e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles                if (output_channels == 2 && input_channels == 1) {
1206e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles                    // Offset into the output stream data in samples.
1207e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles                    ssize_t output_stream_offset = 0;
1208e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles                    for (ssize_t input_stream_frame = 0; input_stream_frame < frames_read;
1209e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles                         input_stream_frame++, output_stream_offset += 2) {
1210e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles                        // Average the content from both channels.
1211e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles                        data[input_stream_frame] = ((int32_t)data[output_stream_offset] +
1212e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles                                                    (int32_t)data[output_stream_offset + 1]) / 2;
1213e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles                    }
1214e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles                } else if (output_channels == 1 && input_channels == 2) {
1215e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles                    // Offset into the input stream data in samples.
1216e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles                    ssize_t input_stream_offset = (frames_read - 1) * 2;
1217e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles                    for (ssize_t output_stream_frame = frames_read - 1; output_stream_frame >= 0;
1218e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles                         output_stream_frame--, input_stream_offset -= 2) {
1219e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles                        const short sample = data[output_stream_frame];
1220e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles                        data[input_stream_offset] = sample;
1221e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles                        data[input_stream_offset + 1] = sample;
1222e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles                    }
1223e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles                }
1224e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles            }
1225e54c12cd532dc36286d500c03ad638402254d4e5Stewart Miles#endif // ENABLE_CHANNEL_CONVERSION
12263dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles
122702c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#if ENABLE_RESAMPLING
122802c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles            if (resampler_ratio != 1.0f) {
122902c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles                SUBMIX_ALOGV("in_read(): resampling %zd frames", frames_read);
123002c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles                const int16_t * const data = (int16_t*)buff;
123102c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles                int16_t * const resampled_buffer = (int16_t*)saved_buff;
123202c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles                // Resample with *no* filtering - if the data from the ouptut stream was really
123302c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles                // sampled at a different rate this will result in very nasty aliasing.
123402c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles                const float output_stream_frames = (float)frames_read;
123502c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles                size_t input_stream_frame = 0;
123602c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles                for (float output_stream_frame = 0.0f;
123702c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles                     output_stream_frame < output_stream_frames &&
123802c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles                     input_stream_frame < remaining_frames;
123902c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles                     output_stream_frame += resampler_ratio, input_stream_frame++) {
124002c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles                    resampled_buffer[input_stream_frame] = data[(size_t)output_stream_frame];
124102c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles                }
124202c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles                ALOG_ASSERT(input_stream_frame <= (ssize_t)resampler_buffer_size_frames);
124302c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles                SUBMIX_ALOGV("in_read(): resampler produced %zd frames", input_stream_frame);
124402c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles                frames_read = input_stream_frame;
124502c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles                buff = saved_buff;
124602c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles            }
124702c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles#endif // ENABLE_RESAMPLING
124802c2f7126c78334ffb20d95f68284f4ec5bdae02Stewart Miles
1249eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi            if (frames_read > 0) {
125092854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#if LOG_STREAMS_TO_FILES
125192854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles                if (in->log_fd >= 0) write(in->log_fd, buff, frames_read * frame_size);
125292854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#endif // LOG_STREAMS_TO_FILES
125392854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles
1254eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi                remaining_frames -= frames_read;
1255eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi                buff += frames_read * frame_size;
1256c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles                SUBMIX_ALOGV("  in_read (att=%d) got %zd frames, remaining=%zu",
1257c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles                             attempts, frames_read, remaining_frames);
1258eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi            } else {
12593dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles                attempts++;
1260c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles                SUBMIX_ALOGE("  in_read read returned %zd", frames_read);
1261eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi                usleep(READ_ATTEMPT_SLEEP_MS * 1000);
1262eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi            }
126388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi        }
1264eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi        // done using the source
1265f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles        pthread_mutex_lock(&rsxadev->lock);
1266eafbfa4058370f113bd94d597f54f28ba41c8a96Jean-Michel Trivi        source.clear();
1267f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles        pthread_mutex_unlock(&rsxadev->lock);
126888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    }
126988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
12706acd966320c7f124f103044f3a152d90d6e38749Jean-Michel Trivi    if (remaining_frames > 0) {
12713dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        const size_t remaining_bytes = remaining_frames * frame_size;
127210f1a806e6537835de7f71dbc05db1889436732eStewart Miles        SUBMIX_ALOGV("  clearing remaining_frames = %zu", remaining_frames);
12733dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        memset(((char*)buffer)+ bytes - remaining_bytes, 0, remaining_bytes);
12746acd966320c7f124f103044f3a152d90d6e38749Jean-Michel Trivi    }
127588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
1276eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi    // compute how much we need to sleep after reading the data by comparing the wall clock with
1277eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi    //   the projected time at which we should return.
1278eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi    struct timespec time_after_read;// wall clock after reading from the pipe
1279eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi    struct timespec record_duration;// observed record duration
1280eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi    int rc = clock_gettime(CLOCK_MONOTONIC, &time_after_read);
1281eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi    const uint32_t sample_rate = in_get_sample_rate(&stream->common);
1282eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi    if (rc == 0) {
1283eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi        // for how long have we been recording?
1284eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi        record_duration.tv_sec  = time_after_read.tv_sec - in->record_start_time.tv_sec;
1285eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi        record_duration.tv_nsec = time_after_read.tv_nsec - in->record_start_time.tv_nsec;
1286eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi        if (record_duration.tv_nsec < 0) {
1287eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi            record_duration.tv_sec--;
1288eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi            record_duration.tv_nsec += 1000000000;
1289eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi        }
1290eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi
1291f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles        // read_counter_frames contains the number of frames that have been read since the
1292f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles        // beginning of recording (including this call): it's converted to usec and compared to
1293f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles        // how long we've been recording for, which gives us how long we must wait to sync the
1294f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles        // projected recording time, and the observed recording time.
1295eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi        long projected_vs_observed_offset_us =
1296eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi                ((int64_t)(in->read_counter_frames
1297eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi                            - (record_duration.tv_sec*sample_rate)))
1298eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi                        * 1000000 / sample_rate
1299eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi                - (record_duration.tv_nsec / 1000);
1300eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi
1301c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles        SUBMIX_ALOGV("  record duration %5lds %3ldms, will wait: %7ldus",
1302eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi                record_duration.tv_sec, record_duration.tv_nsec/1000000,
1303eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi                projected_vs_observed_offset_us);
1304eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi        if (projected_vs_observed_offset_us > 0) {
1305eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi            usleep(projected_vs_observed_offset_us);
1306eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi        }
130788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    }
1308eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi
1309c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    SUBMIX_ALOGV("in_read returns %zu", bytes);
1310eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi    return bytes;
1311eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi
131288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
131388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
131488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
131588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
1316c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)stream;
131788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    return 0;
131888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
131988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
132088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
132188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
1322c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)stream;
1323c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)effect;
132488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    return 0;
132588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
132688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
132788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
132888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
1329c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)stream;
1330c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)effect;
133188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    return 0;
133288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
133388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
133488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int adev_open_output_stream(struct audio_hw_device *dev,
133588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi                                   audio_io_handle_t handle,
133688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi                                   audio_devices_t devices,
133788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi                                   audio_output_flags_t flags,
133888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi                                   struct audio_config *config,
1339f5e2469c02825f018df6336125882812003b8e64Eric Laurent                                   struct audio_stream_out **stream_out,
1340b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi                                   const char *address)
134188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
1342f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles    struct submix_audio_device * const rsxadev = audio_hw_device_get_submix_audio_device(dev);
1343b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    ALOGD("adev_open_output_stream(address=%s)", address);
134488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    struct submix_stream_out *out;
134510f1a806e6537835de7f71dbc05db1889436732eStewart Miles    bool force_pipe_creation = false;
1346c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)handle;
1347c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)devices;
1348c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)flags;
134988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
13503dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    *stream_out = NULL;
13513dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles
13527072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    // Make sure it's possible to open the device given the current audio config.
13537072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    submix_sanitize_config(config, false);
1354b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi
1355b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    int route_idx = -1;
1356b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi
1357b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    pthread_mutex_lock(&rsxadev->lock);
1358b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi
1359b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    status_t res = submix_get_route_idx_for_address_l(rsxadev, address, &route_idx);
1360b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    if (res != OK) {
1361b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        ALOGE("Error %d looking for address=%s in adev_open_output_stream", res, address);
1362b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        pthread_mutex_unlock(&rsxadev->lock);
1363b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        return res;
1364b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    }
1365b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi
1366b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    if (!submix_open_validate_l(rsxadev, route_idx, config, false)) {
1367b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        ALOGE("adev_open_output_stream(): Unable to open output stream for address %s", address);
1368b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        pthread_mutex_unlock(&rsxadev->lock);
13697072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles        return -EINVAL;
13707072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    }
13717072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles
137288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    out = (struct submix_stream_out *)calloc(1, sizeof(struct submix_stream_out));
1373b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    if (!out) {
1374b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        pthread_mutex_unlock(&rsxadev->lock);
1375b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        return -ENOMEM;
1376b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    }
137788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
1378568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles    // Initialize the function pointer tables (v-tables).
137988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    out->stream.common.get_sample_rate = out_get_sample_rate;
138088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    out->stream.common.set_sample_rate = out_set_sample_rate;
138188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    out->stream.common.get_buffer_size = out_get_buffer_size;
138288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    out->stream.common.get_channels = out_get_channels;
138388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    out->stream.common.get_format = out_get_format;
138488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    out->stream.common.set_format = out_set_format;
138588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    out->stream.common.standby = out_standby;
138688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    out->stream.common.dump = out_dump;
138788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    out->stream.common.set_parameters = out_set_parameters;
138888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    out->stream.common.get_parameters = out_get_parameters;
138988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    out->stream.common.add_audio_effect = out_add_audio_effect;
139088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    out->stream.common.remove_audio_effect = out_remove_audio_effect;
139188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    out->stream.get_latency = out_get_latency;
139288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    out->stream.set_volume = out_set_volume;
139388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    out->stream.write = out_write;
139488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    out->stream.get_render_position = out_get_render_position;
139588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
139625f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi    out->stream.get_presentation_position = out_get_presentation_position;
139725f4751f6d0992ec4f988fd4f51f36140a28d0e2Jean-Michel Trivi
139810f1a806e6537835de7f71dbc05db1889436732eStewart Miles#if ENABLE_RESAMPLING
139910f1a806e6537835de7f71dbc05db1889436732eStewart Miles    // Recreate the pipe with the correct sample rate so that MonoPipe.write() rate limits
140010f1a806e6537835de7f71dbc05db1889436732eStewart Miles    // writes correctly.
1401b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    force_pipe_creation = rsxadev->routes[route_idx].config.common.sample_rate
1402b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi            != config->sample_rate;
140310f1a806e6537835de7f71dbc05db1889436732eStewart Miles#endif // ENABLE_RESAMPLING
140410f1a806e6537835de7f71dbc05db1889436732eStewart Miles
140510f1a806e6537835de7f71dbc05db1889436732eStewart Miles    // If the sink has been shutdown or pipe recreation is forced (see above), delete the pipe so
140610f1a806e6537835de7f71dbc05db1889436732eStewart Miles    // that it's recreated.
1407b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    if ((rsxadev->routes[route_idx].rsxSink != NULL
1408b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi            && rsxadev->routes[route_idx].rsxSink->isShutdown()) || force_pipe_creation) {
1409b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        submix_audio_device_release_pipe_l(rsxadev, route_idx);
14103dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    }
141188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
1412568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles    // Store a pointer to the device from the output stream.
1413568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles    out->dev = rsxadev;
14143dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    // Initialize the pipe.
1415b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    ALOGV("adev_open_output_stream(): about to create pipe at index %d", route_idx);
1416b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    submix_audio_device_create_pipe_l(rsxadev, config, DEFAULT_PIPE_SIZE_IN_FRAMES,
1417b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi            DEFAULT_PIPE_PERIOD_COUNT, NULL, out, address, route_idx);
141892854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#if LOG_STREAMS_TO_FILES
141992854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles    out->log_fd = open(LOG_STREAM_OUT_FILENAME, O_CREAT | O_TRUNC | O_WRONLY,
142092854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles                       LOG_STREAM_FILE_PERMISSIONS);
142192854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles    ALOGE_IF(out->log_fd < 0, "adev_open_output_stream(): log file open failed %s",
142292854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles             strerror(errno));
142392854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles    ALOGV("adev_open_output_stream(): log_fd = %d", out->log_fd);
142492854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#endif // LOG_STREAMS_TO_FILES
1425568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles    // Return the output stream.
142688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    *stream_out = &out->stream;
142788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
1428b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    pthread_mutex_unlock(&rsxadev->lock);
142988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    return 0;
143088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
143188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
143288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic void adev_close_output_stream(struct audio_hw_device *dev,
143388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi                                     struct audio_stream_out *stream)
143488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
1435b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    struct submix_audio_device * rsxadev = audio_hw_device_get_submix_audio_device(
1436b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi                    const_cast<struct audio_hw_device*>(dev));
14373dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    struct submix_stream_out * const out = audio_stream_out_get_submix_stream_out(stream);
1438b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi
1439b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    pthread_mutex_lock(&rsxadev->lock);
1440b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    ALOGD("adev_close_output_stream() addr = %s", rsxadev->routes[out->route_handle].address);
1441b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    submix_audio_device_destroy_pipe_l(audio_hw_device_get_submix_audio_device(dev), NULL, out);
144292854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#if LOG_STREAMS_TO_FILES
144392854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles    if (out->log_fd >= 0) close(out->log_fd);
144492854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#endif // LOG_STREAMS_TO_FILES
1445b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi
1446b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    pthread_mutex_unlock(&rsxadev->lock);
14473dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    free(out);
144888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
144988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
145088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
145188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
1452c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)dev;
1453c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)kvpairs;
145488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    return -ENOSYS;
145588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
145688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
145788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic char * adev_get_parameters(const struct audio_hw_device *dev,
145888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi                                  const char *keys)
145988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
1460c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)dev;
1461c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)keys;
146288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    return strdup("");;
146388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
146488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
146588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int adev_init_check(const struct audio_hw_device *dev)
146688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
146788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    ALOGI("adev_init_check()");
1468c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)dev;
146988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    return 0;
147088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
147188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
147288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
147388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
1474c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)dev;
1475c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)volume;
147688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    return -ENOSYS;
147788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
147888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
147988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int adev_set_master_volume(struct audio_hw_device *dev, float volume)
148088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
1481c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)dev;
1482c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)volume;
148388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    return -ENOSYS;
148488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
148588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
148688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int adev_get_master_volume(struct audio_hw_device *dev, float *volume)
148788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
1488c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)dev;
1489c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)volume;
149088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    return -ENOSYS;
149188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
149288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
149388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int adev_set_master_mute(struct audio_hw_device *dev, bool muted)
149488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
1495c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)dev;
1496c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)muted;
149788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    return -ENOSYS;
149888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
149988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
150088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int adev_get_master_mute(struct audio_hw_device *dev, bool *muted)
150188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
1502c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)dev;
1503c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)muted;
150488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    return -ENOSYS;
150588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
150688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
150788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
150888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
1509c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)dev;
1510c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)mode;
151188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    return 0;
151288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
151388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
151488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
151588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
1516c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)dev;
1517c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)state;
151888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    return -ENOSYS;
151988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
152088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
152188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
152288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
1523c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)dev;
1524c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)state;
152588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    return -ENOSYS;
152688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
152788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
152888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
152988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi                                         const struct audio_config *config)
153088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
1531568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles    if (audio_is_linear_pcm(config->format)) {
1532b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        size_t max_buffer_period_size_frames = 0;
1533b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        struct submix_audio_device * rsxadev = audio_hw_device_get_submix_audio_device(
1534b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi                const_cast<struct audio_hw_device*>(dev));
1535b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        // look for the largest buffer period size
1536b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        for (int i = 0 ; i < MAX_ROUTES ; i++) {
1537b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi            if (rsxadev->routes[i].config.buffer_period_size_frames > max_buffer_period_size_frames)
1538b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi            {
1539b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi                max_buffer_period_size_frames = rsxadev->routes[i].config.buffer_period_size_frames;
1540b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi            }
1541b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        }
1542dd45fd3aede6b116656a60a2d9b6e286d19f030fEric Laurent        const size_t frame_size_in_bytes = audio_channel_count_from_in_mask(config->channel_mask) *
1543568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles                audio_bytes_per_sample(config->format);
1544b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        const size_t buffer_size = max_buffer_period_size_frames * frame_size_in_bytes;
154510f1a806e6537835de7f71dbc05db1889436732eStewart Miles        SUBMIX_ALOGV("adev_get_input_buffer_size() returns %zu bytes, %zu frames",
1546568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles                 buffer_size, buffer_period_size_frames);
1547568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles        return buffer_size;
1548568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles    }
1549568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles    return 0;
155088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
155188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
155288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int adev_open_input_stream(struct audio_hw_device *dev,
155388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi                                  audio_io_handle_t handle,
155488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi                                  audio_devices_t devices,
155588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi                                  struct audio_config *config,
15567d973adff4c9b344b530dd7c585f789d02c605daGlenn Kasten                                  struct audio_stream_in **stream_in,
1557f5e2469c02825f018df6336125882812003b8e64Eric Laurent                                  audio_input_flags_t flags __unused,
1558b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi                                  const char *address,
1559f5e2469c02825f018df6336125882812003b8e64Eric Laurent                                  audio_source_t source __unused)
156088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
1561f645c5e629147628957cb8d66ce3405f242fd2e9Stewart Miles    struct submix_audio_device *rsxadev = audio_hw_device_get_submix_audio_device(dev);
156288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    struct submix_stream_in *in;
1563b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    ALOGD("adev_open_input_stream(addr=%s)", address);
1564c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)handle;
1565c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles    (void)devices;
156688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
15673dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    *stream_in = NULL;
15683dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles
1569b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    // Do we already have a route for this address
1570b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    int route_idx = -1;
1571b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi
1572b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    pthread_mutex_lock(&rsxadev->lock);
1573b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi
1574b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    status_t res = submix_get_route_idx_for_address_l(rsxadev, address, &route_idx);
1575b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    if (res != OK) {
157679fbccf91be4d98d0e04dd840f1ccf156fab2ae3Jean-Michel Trivi        ALOGE("Error %d looking for address=%s in adev_open_input_stream", res, address);
1577b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        pthread_mutex_unlock(&rsxadev->lock);
1578b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        return res;
1579b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    }
1580b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi
15817072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    // Make sure it's possible to open the device given the current audio config.
15827072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    submix_sanitize_config(config, true);
1583b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    if (!submix_open_validate_l(rsxadev, route_idx, config, true)) {
15847072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles        ALOGE("adev_open_input_stream(): Unable to open input stream.");
1585b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        pthread_mutex_unlock(&rsxadev->lock);
15867072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles        return -EINVAL;
15877072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles    }
15887072684fbfc73b0dd92dc010f418b3919221f1d8Stewart Miles
15893dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles#if ENABLE_LEGACY_INPUT_OPEN
1590b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    in = rsxadev->routes[route_idx].input;
15913dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    if (in) {
15923dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        in->ref_count++;
1593b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        sp<MonoPipe> sink = rsxadev->routes[route_idx].rsxSink;
15943dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        ALOG_ASSERT(sink != NULL);
15953dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        // If the sink has been shutdown, delete the pipe.
1596793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi        if (sink != NULL) {
1597793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi            if (sink->isShutdown()) {
1598793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi                ALOGD(" Non-NULL shut down sink when opening input stream, releasing, refcount=%d",
1599793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi                        in->ref_count);
1600b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi                submix_audio_device_release_pipe_l(rsxadev, in->route_handle);
1601793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi            } else {
1602793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi                ALOGD(" Non-NULL sink when opening input stream, refcount=%d", in->ref_count);
1603793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi            }
1604793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi        } else {
1605793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi            ALOGE("NULL sink when opening input stream, refcount=%d", in->ref_count);
1606793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi        }
16073dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    }
16083dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles#else
16093dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    in = NULL;
16103dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles#endif // ENABLE_LEGACY_INPUT_OPEN
161188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
16123dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    if (!in) {
16133dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        in = (struct submix_stream_in *)calloc(1, sizeof(struct submix_stream_in));
16143dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        if (!in) return -ENOMEM;
16153dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        in->ref_count = 1;
16163dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles
16173dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        // Initialize the function pointer tables (v-tables).
16183dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        in->stream.common.get_sample_rate = in_get_sample_rate;
16193dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        in->stream.common.set_sample_rate = in_set_sample_rate;
16203dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        in->stream.common.get_buffer_size = in_get_buffer_size;
16213dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        in->stream.common.get_channels = in_get_channels;
16223dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        in->stream.common.get_format = in_get_format;
16233dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        in->stream.common.set_format = in_set_format;
16243dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        in->stream.common.standby = in_standby;
16253dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        in->stream.common.dump = in_dump;
16263dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        in->stream.common.set_parameters = in_set_parameters;
16273dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        in->stream.common.get_parameters = in_get_parameters;
16283dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        in->stream.common.add_audio_effect = in_add_audio_effect;
16293dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        in->stream.common.remove_audio_effect = in_remove_audio_effect;
16303dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        in->stream.set_gain = in_set_gain;
16313dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        in->stream.read = in_read;
16323dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles        in->stream.get_input_frames_lost = in_get_input_frames_lost;
1633b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi
1634b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        in->dev = rsxadev;
1635b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi#if LOG_STREAMS_TO_FILES
1636b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        in->log_fd = -1;
1637b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi#endif
16383dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    }
163988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
1640568e66ff9e0d6be92ba994e8054f78a0fb8726e2Stewart Miles    // Initialize the input stream.
1641eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi    in->read_counter_frames = 0;
1642b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    in->input_standby = true;
1643b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    if (rsxadev->routes[route_idx].output != NULL) {
1644b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        in->output_standby_rec_thr = rsxadev->routes[route_idx].output->output_standby;
1645b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    } else {
1646b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        in->output_standby_rec_thr = true;
1647b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    }
1648b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi
1649793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi    in->read_error_count = 0;
16503dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    // Initialize the pipe.
1651793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi    ALOGV("adev_open_input_stream(): about to create pipe");
1652b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    submix_audio_device_create_pipe_l(rsxadev, config, DEFAULT_PIPE_SIZE_IN_FRAMES,
1653b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi                                    DEFAULT_PIPE_PERIOD_COUNT, in, NULL, address, route_idx);
165492854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#if LOG_STREAMS_TO_FILES
1655b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    if (in->log_fd >= 0) close(in->log_fd);
165692854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles    in->log_fd = open(LOG_STREAM_IN_FILENAME, O_CREAT | O_TRUNC | O_WRONLY,
165792854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles                      LOG_STREAM_FILE_PERMISSIONS);
165892854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles    ALOGE_IF(in->log_fd < 0, "adev_open_input_stream(): log file open failed %s",
165992854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles             strerror(errno));
166092854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles    ALOGV("adev_open_input_stream(): log_fd = %d", in->log_fd);
166192854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#endif // LOG_STREAMS_TO_FILES
16623dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    // Return the input stream.
16633dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    *stream_in = &in->stream;
166488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
1665b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    pthread_mutex_unlock(&rsxadev->lock);
166688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    return 0;
166788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
166888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
166988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic void adev_close_input_stream(struct audio_hw_device *dev,
1670c049a0a3a9cdc0ba4cbc5fe8524e67ae39b1dd9aStewart Miles                                    struct audio_stream_in *stream)
167188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
1672b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    struct submix_audio_device * const rsxadev = audio_hw_device_get_submix_audio_device(dev);
1673b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi
16743dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    struct submix_stream_in * const in = audio_stream_in_get_submix_stream_in(stream);
1675793a854e4547fa43632907a987684cadc93eb5e2Jean-Michel Trivi    ALOGD("adev_close_input_stream()");
1676b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    pthread_mutex_lock(&rsxadev->lock);
1677b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    submix_audio_device_destroy_pipe_l(rsxadev, in, NULL);
167892854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#if LOG_STREAMS_TO_FILES
167992854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles    if (in->log_fd >= 0) close(in->log_fd);
168092854f5fcced958e5888074fc4e68ad0ec67aeefStewart Miles#endif // LOG_STREAMS_TO_FILES
16813dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles#if ENABLE_LEGACY_INPUT_OPEN
16823dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    if (in->ref_count == 0) free(in);
16833dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles#else
16843dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles    free(in);
16853dd36f959532db801e65ea160623e94a0e7fd3a9Stewart Miles#endif // ENABLE_LEGACY_INPUT_OPEN
1686b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi
1687b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    pthread_mutex_unlock(&rsxadev->lock);
168888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
168988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
169088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int adev_dump(const audio_hw_device_t *device, int fd)
169188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
1692b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    const struct submix_audio_device * rsxadev = //audio_hw_device_get_submix_audio_device(device);
1693b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi            reinterpret_cast<const struct submix_audio_device *>(
1694b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi                    reinterpret_cast<const uint8_t *>(device) -
1695b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi                            offsetof(struct submix_audio_device, device));
1696b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    char msg[100];
1697b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    int n = sprintf(msg, "\nReroute submix audio module:\n");
1698b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    write(fd, &msg, n);
1699b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    for (int i=0 ; i < MAX_ROUTES ; i++) {
1700b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        n = sprintf(msg, " route[%d] rate in=%d out=%d, addr=[%s]\n", i,
1701b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi                rsxadev->routes[i].config.input_sample_rate,
1702b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi                rsxadev->routes[i].config.output_sample_rate,
1703b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi                rsxadev->routes[i].address);
1704b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        write(fd, &msg, n);
1705b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    }
170688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    return 0;
170788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
170888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
170988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int adev_close(hw_device_t *device)
171088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
171188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    ALOGI("adev_close()");
171288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    free(device);
171388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    return 0;
171488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
171588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
171688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic int adev_open(const hw_module_t* module, const char* name,
171788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi                     hw_device_t** device)
171888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi{
171988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    ALOGI("adev_open(name=%s)", name);
172088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    struct submix_audio_device *rsxadev;
172188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
172288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
172388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi        return -EINVAL;
172488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
172588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    rsxadev = (submix_audio_device*) calloc(1, sizeof(struct submix_audio_device));
172688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    if (!rsxadev)
172788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi        return -ENOMEM;
172888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
172988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    rsxadev->device.common.tag = HARDWARE_DEVICE_TAG;
17305d85c537fcae931428ba8b7a47fdd393cc3cbd88Eric Laurent    rsxadev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
173188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    rsxadev->device.common.module = (struct hw_module_t *) module;
173288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    rsxadev->device.common.close = adev_close;
173388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
173488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    rsxadev->device.init_check = adev_init_check;
173588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    rsxadev->device.set_voice_volume = adev_set_voice_volume;
173688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    rsxadev->device.set_master_volume = adev_set_master_volume;
173788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    rsxadev->device.get_master_volume = adev_get_master_volume;
173888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    rsxadev->device.set_master_mute = adev_set_master_mute;
173988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    rsxadev->device.get_master_mute = adev_get_master_mute;
174088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    rsxadev->device.set_mode = adev_set_mode;
174188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    rsxadev->device.set_mic_mute = adev_set_mic_mute;
174288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    rsxadev->device.get_mic_mute = adev_get_mic_mute;
174388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    rsxadev->device.set_parameters = adev_set_parameters;
174488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    rsxadev->device.get_parameters = adev_get_parameters;
174588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    rsxadev->device.get_input_buffer_size = adev_get_input_buffer_size;
174688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    rsxadev->device.open_output_stream = adev_open_output_stream;
174788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    rsxadev->device.close_output_stream = adev_close_output_stream;
174888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    rsxadev->device.open_input_stream = adev_open_input_stream;
174988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    rsxadev->device.close_input_stream = adev_close_input_stream;
175088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    rsxadev->device.dump = adev_dump;
175188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
1752b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi    for (int i=0 ; i < MAX_ROUTES ; i++) {
1753b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi            memset(&rsxadev->routes[i], 0, sizeof(route_config));
1754b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi            strcpy(rsxadev->routes[i].address, "");
1755b73bc86089b8a65da88776bafcf48529431150b8Jean-Michel Trivi        }
1756eec87706d21fc0ac4ad10ede86943770b2533564Jean-Michel Trivi
175788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    *device = &rsxadev->device.common;
175888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
175988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    return 0;
176088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi}
176188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
176288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistatic struct hw_module_methods_t hal_module_methods = {
176388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    /* open */ adev_open,
176488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi};
176588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
176688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivistruct audio_module HAL_MODULE_INFO_SYM = {
176788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    /* common */ {
176888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi        /* tag */                HARDWARE_MODULE_TAG,
176988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi        /* module_api_version */ AUDIO_MODULE_API_VERSION_0_1,
177088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi        /* hal_api_version */    HARDWARE_HAL_API_VERSION,
177188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi        /* id */                 AUDIO_HARDWARE_MODULE_ID,
177288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi        /* name */               "Wifi Display audio HAL",
177388b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi        /* author */             "The Android Open Source Project",
177488b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi        /* methods */            &hal_module_methods,
177588b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi        /* dso */                NULL,
177688b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi        /* reserved */           { 0 },
177788b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi    },
177888b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi};
177988b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
178088b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} //namespace android
178188b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi
178288b79cb001d1c733275c7cad490c32b143f78860Jean-Michel Trivi} //extern "C"
1783