#include "hal-log.h"
#include "hal-msg.h"
#include "hal-audio.h"
-#include "src/shared/util.h"
-#include "src/shared/queue.h"
+#include "hal-utils.h"
+#include "hal.h"
#define FIXED_A2DP_PLAYBACK_LATENCY_MS 25
return res.tv_sec * 1000000ll + res.tv_nsec / 1000ll;
}
-#if defined(ANDROID)
+#if ANDROID_VERSION < PLATFORM_VER(6, 0, 0)
/*
* Bionic does not have clock_nanosleep() prototype in time.h even though
* it provides its implementation.
struct timespec *remain);
#endif
-static const audio_codec_get_t audio_codecs[] = {
- codec_sbc,
+static struct {
+ const audio_codec_get_t get_codec;
+ bool loaded;
+} audio_codecs[] = {
+ { .get_codec = codec_aptx, .loaded = false },
+ { .get_codec = codec_sbc, .loaded = false },
};
#define NUM_CODECS (sizeof(audio_codecs) / sizeof(audio_codecs[0]))
#define MAX_AUDIO_ENDPOINTS NUM_CODECS
-static struct queue *loaded_codecs;
-
struct audio_endpoint {
uint8_t id;
const struct audio_codec *codec;
goto failed;
}
- if (rsp_len)
- *rsp_len = cmd.len;
+ *rsp_len = cmd.len;
return AUDIO_STATUS_SUCCESS;
bool error;
};
-static void register_endpoint(void *data, void *user_data)
+static void register_endpoint(const struct audio_codec *codec,
+ struct register_state *state)
{
- struct audio_codec *codec = data;
- struct register_state *state = user_data;
struct audio_endpoint *ep = state->ep;
/* don't even try to register more endpoints if one failed */
static int register_endpoints(void)
{
struct register_state state;
+ unsigned int i;
state.ep = &audio_endpoints[0];
state.error = false;
- queue_foreach(loaded_codecs, register_endpoint, &state);
+ for (i = 0; i < NUM_CODECS; i++) {
+ const struct audio_codec *codec = audio_codecs[i].get_codec();
+
+ if (!audio_codecs[i].loaded)
+ continue;
+
+ register_endpoint(codec, &state);
+ }
return state.error ? AUDIO_STATUS_FAILED : AUDIO_STATUS_SUCCESS;
}
if (!ep) {
error("Cound not find opened endpoint");
- return false;
+ goto failed;
}
*epp = ep;
frames = bytes / (2 * sizeof(int16_t));
for (i = 0; i < frames; i++) {
- int16_t l = le16_to_cpu(get_unaligned(&input[i * 2]));
- int16_t r = le16_to_cpu(get_unaligned(&input[i * 2 + 1]));
+ int16_t l = get_le16(&input[i * 2]);
+ int16_t r = get_le16(&input[i * 2 + 1]);
- put_unaligned(cpu_to_le16((l + r) / 2), &output[i]);
+ put_le16((l + r) / 2, &output[i]);
}
}
return -ENOSYS;
}
-static int audio_open_output_stream(struct audio_hw_device *dev,
+static int audio_open_output_stream_real(struct audio_hw_device *dev,
audio_io_handle_t handle,
audio_devices_t devices,
audio_output_flags_t flags,
struct audio_config *config,
- struct audio_stream_out **stream_out)
-
+ struct audio_stream_out **stream_out,
+ const char *address)
{
struct a2dp_audio_dev *a2dp_dev = (struct a2dp_audio_dev *) dev;
struct a2dp_stream_out *out;
return -EIO;
}
+#if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
+static int audio_open_output_stream(struct audio_hw_device *dev,
+ audio_io_handle_t handle,
+ audio_devices_t devices,
+ audio_output_flags_t flags,
+ struct audio_config *config,
+ struct audio_stream_out **stream_out,
+ const char *address)
+{
+ return audio_open_output_stream_real(dev, handle, devices, flags,
+ config, stream_out, address);
+}
+#else
+static int audio_open_output_stream(struct audio_hw_device *dev,
+ audio_io_handle_t handle,
+ audio_devices_t devices,
+ audio_output_flags_t flags,
+ struct audio_config *config,
+ struct audio_stream_out **stream_out)
+{
+ return audio_open_output_stream_real(dev, handle, devices, flags,
+ config, stream_out, NULL);
+}
+#endif
+
static void audio_close_output_stream(struct audio_hw_device *dev,
struct audio_stream_out *stream)
{
return -ENOSYS;
}
-static int audio_open_input_stream(struct audio_hw_device *dev,
+static int audio_open_input_stream_real(struct audio_hw_device *dev,
audio_io_handle_t handle,
audio_devices_t devices,
struct audio_config *config,
- struct audio_stream_in **stream_in)
+ struct audio_stream_in **stream_in,
+ audio_input_flags_t flags,
+ const char *address,
+ audio_source_t source)
{
struct audio_stream_in *in;
return 0;
}
+#if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
+static int audio_open_input_stream(struct audio_hw_device *dev,
+ audio_io_handle_t handle,
+ audio_devices_t devices,
+ struct audio_config *config,
+ struct audio_stream_in **stream_in,
+ audio_input_flags_t flags,
+ const char *address,
+ audio_source_t source)
+{
+ return audio_open_input_stream_real(dev, handle, devices, config,
+ stream_in, flags, address,
+ source);
+}
+#else
+static int audio_open_input_stream(struct audio_hw_device *dev,
+ audio_io_handle_t handle,
+ audio_devices_t devices,
+ struct audio_config *config,
+ struct audio_stream_in **stream_in)
+{
+ return audio_open_input_stream_real(dev, handle, devices, config,
+ stream_in, 0, NULL, 0);
+}
+#endif
+
static void audio_close_input_stream(struct audio_hw_device *dev,
struct audio_stream_in *stream_in)
{
return -ENOSYS;
}
-static void unload_codec(void *data)
+#if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
+static int set_master_mute(struct audio_hw_device *dev, bool mute)
+{
+ DBG("");
+ return -ENOSYS;
+}
+
+static int get_master_mute(struct audio_hw_device *dev, bool *mute)
+{
+ DBG("");
+ return -ENOSYS;
+}
+
+static int create_audio_patch(struct audio_hw_device *dev,
+ unsigned int num_sources,
+ const struct audio_port_config *sources,
+ unsigned int num_sinks,
+ const struct audio_port_config *sinks,
+ audio_patch_handle_t *handle)
{
- struct audio_codec *codec = data;
+ DBG("");
+ return -ENOSYS;
+}
- if (codec->unload)
- codec->unload();
+static int release_audio_patch(struct audio_hw_device *dev,
+ audio_patch_handle_t handle)
+{
+ DBG("");
+ return -ENOSYS;
+}
+
+static int get_audio_port(struct audio_hw_device *dev, struct audio_port *port)
+{
+ DBG("");
+ return -ENOSYS;
}
+static int set_audio_port_config(struct audio_hw_device *dev,
+ const struct audio_port_config *config)
+{
+ DBG("");
+ return -ENOSYS;
+}
+#endif
+
static int audio_close(hw_device_t *device)
{
struct a2dp_audio_dev *a2dp_dev = (struct a2dp_audio_dev *)device;
+ unsigned int i;
DBG("");
unregister_endpoints();
- queue_destroy(loaded_codecs, unload_codec);
- loaded_codecs = NULL;
+ for (i = 0; i < NUM_CODECS; i++) {
+ const struct audio_codec *codec = audio_codecs[i].get_codec();
+
+ if (!audio_codecs[i].loaded)
+ continue;
+
+ if (codec->unload)
+ codec->unload();
+
+ audio_codecs[i].loaded = false;
+ }
shutdown(listen_sk, SHUT_RDWR);
shutdown(audio_sk, SHUT_RDWR);
/* Check if socket is still alive. Empty while loop.*/
while (poll(&pfd, 1, -1) < 0 && errno == EINTR);
- if (pfd.revents & (POLLHUP | POLLERR | POLLNVAL)) {
- info("Audio HAL: Socket closed");
+ info("Audio HAL: Socket closed");
- pthread_mutex_lock(&sk_mutex);
- close(audio_sk);
- audio_sk = -1;
- pthread_mutex_unlock(&sk_mutex);
- }
+ pthread_mutex_lock(&sk_mutex);
+ close(audio_sk);
+ audio_sk = -1;
+ pthread_mutex_unlock(&sk_mutex);
}
/* audio_sk is closed at this point, just cleanup endpoints states */
a2dp_dev->dev.open_input_stream = audio_open_input_stream;
a2dp_dev->dev.close_input_stream = audio_close_input_stream;
a2dp_dev->dev.dump = audio_dump;
-
- loaded_codecs = queue_new();
+#if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
+ a2dp_dev->dev.set_master_mute = set_master_mute;
+ a2dp_dev->dev.get_master_mute = get_master_mute;
+ a2dp_dev->dev.create_audio_patch = create_audio_patch;
+ a2dp_dev->dev.release_audio_patch = release_audio_patch;
+ a2dp_dev->dev.get_audio_port = get_audio_port;
+ a2dp_dev->dev.set_audio_port_config = set_audio_port_config;
+#endif
for (i = 0; i < NUM_CODECS; i++) {
- audio_codec_get_t get_codec = audio_codecs[i];
- const struct audio_codec *codec = get_codec();
+ const struct audio_codec *codec = audio_codecs[i].get_codec();
if (codec->load && !codec->load())
continue;
- queue_push_tail(loaded_codecs, (void *) codec);
+ audio_codecs[i].loaded = true;
}
/*