Extensions to the audio HAL to send audio data to a ringbuffer inside
vsoc shared memory. Adds "record_audio" tool to sniff from the ringbuffer.
Change-Id: Iaa056a710ea42db2e17b69d33af7d389b77e955d
Bug: 72216799
Test: manually
diff --git a/Android.bp b/Android.bp
index 22d7ec9..124bc8a 100644
--- a/Android.bp
+++ b/Android.bp
@@ -89,6 +89,8 @@
name: "vsoc_lib",
srcs: [
"common/vsoc/lib/compat.cpp",
+ "common/vsoc/lib/audio_data_layout.cpp",
+ "common/vsoc/lib/audio_data_region_view.cpp",
"common/vsoc/lib/e2e_test_region_layout.cpp",
"common/vsoc/lib/fb_bcast_layout.cpp",
"common/vsoc/lib/fb_bcast_region_view.cpp",
diff --git a/common/vsoc/lib/audio_data_layout.cpp b/common/vsoc/lib/audio_data_layout.cpp
new file mode 100644
index 0000000..4b5172c
--- /dev/null
+++ b/common/vsoc/lib/audio_data_layout.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Define some of the string constants associated with the region layout.
+#include "common/vsoc/shm/audio_data_layout.h"
+
+namespace vsoc {
+namespace layout {
+namespace audio_data {
+
+// static
+const char *const AudioDataLayout::region_name = "audio_data";
+
+} // namespace audio_data
+} // namespace layout
+} // namespace vsoc
+
diff --git a/common/vsoc/lib/audio_data_region_view.cpp b/common/vsoc/lib/audio_data_region_view.cpp
new file mode 100644
index 0000000..868cc94
--- /dev/null
+++ b/common/vsoc/lib/audio_data_region_view.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common/vsoc/lib/audio_data_region_view.h"
+
+#include "common/vsoc/lib/circqueue_impl.h"
+
+#include <mutex>
+
+using vsoc::layout::audio_data::AudioDataLayout;
+
+namespace vsoc {
+namespace audio_data {
+
+// static
+AudioDataRegionView *AudioDataRegionView::GetInstance() {
+ static AudioDataRegionView sInstance;
+ return &sInstance;
+}
+
+} // namespace audio_data
+} // namespace vsoc
+
diff --git a/common/vsoc/lib/audio_data_region_view.h b/common/vsoc/lib/audio_data_region_view.h
new file mode 100644
index 0000000..13e51f4
--- /dev/null
+++ b/common/vsoc/lib/audio_data_region_view.h
@@ -0,0 +1,40 @@
+#pragma once
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/macros.h>
+
+#include "common/vsoc/lib/typed_region_view.h"
+#include "common/vsoc/shm/audio_data_layout.h"
+
+namespace vsoc {
+namespace audio_data {
+
+class AudioDataRegionView
+ : public vsoc::TypedRegionView<vsoc::layout::audio_data::AudioDataLayout> {
+public:
+ AudioDataRegionView(const AudioDataRegionView &) = delete;
+ AudioDataRegionView &operator=(const AudioDataRegionView &) = delete;
+
+ static AudioDataRegionView *GetInstance();
+
+private:
+ AudioDataRegionView() = default;
+};
+
+} // namespace audio_data
+} // namespace vsoc
+
diff --git a/common/vsoc/lib/circqueue_impl.h b/common/vsoc/lib/circqueue_impl.h
index 0abd7dd..dc65e4b 100644
--- a/common/vsoc/lib/circqueue_impl.h
+++ b/common/vsoc/lib/circqueue_impl.h
@@ -183,9 +183,27 @@
intptr_t CircularPacketQueue<SizeLog2, MaxPacketSize>::Write(
RegionSignalingInterface* r, const char* buffer_in, uint32_t bytes,
bool non_blocking) {
+ iovec iov;
+ iov.iov_base = const_cast<char *>(buffer_in);
+ iov.iov_len = bytes;
+ return Writev(r, &iov, 1 /* iov_count */, non_blocking);
+}
+
+template <uint32_t SizeLog2, uint32_t MaxPacketSize>
+intptr_t CircularPacketQueue<SizeLog2, MaxPacketSize>::Writev(
+ RegionSignalingInterface *r,
+ const iovec *iov,
+ size_t iov_count,
+ bool non_blocking) {
+ size_t bytes = 0;
+ for (size_t i = 0; i < iov_count; ++i) {
+ bytes += iov[i].iov_len;
+ }
+
if (bytes > MaxPacketSize) {
return -ENOSPC;
}
+
Range range;
size_t buffered_size = this->CalculateBufferedSize(bytes);
this->lock_.Lock();
@@ -201,7 +219,15 @@
static_cast<uint32_t>(range.start_idx + sizeof(uint32_t)),
static_cast<uint32_t>(range.start_idx + sizeof(uint32_t) + bytes)};
this->CopyInRange(reinterpret_cast<const char*>(&bytes), header);
- this->CopyInRange(buffer_in, payload);
+
+ Range subRange = payload;
+ for (size_t i = 0; i < iov_count; ++i) {
+ subRange.end_idx = subRange.start_idx + iov[i].iov_len;
+ this->CopyInRange(static_cast<const char *>(iov[i].iov_base), subRange);
+
+ subRange.start_idx = subRange.end_idx;
+ }
+
this->w_pub_ = range.end_idx;
this->lock_.Unlock();
layout::Sides side;
diff --git a/common/vsoc/shm/audio_data_layout.h b/common/vsoc/shm/audio_data_layout.h
new file mode 100644
index 0000000..d344a8e
--- /dev/null
+++ b/common/vsoc/shm/audio_data_layout.h
@@ -0,0 +1,39 @@
+#pragma once
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common/vsoc/shm/base.h"
+#include "common/vsoc/shm/circqueue.h"
+#include "common/vsoc/shm/version.h"
+
+// Memory layout for region carrying audio data from audio HAL to client.
+
+namespace vsoc {
+namespace layout {
+namespace audio_data {
+
+struct AudioDataLayout : public RegionLayout {
+ static const char *const region_name;
+
+ // size = 2^14 = 16384, packets are up to 4KB bytes each.
+ CircularPacketQueue<14, 4096> audio_queue;
+};
+ASSERT_SHM_COMPATIBLE(AudioDataLayout, audio_data);
+
+} // namespace audio_data
+} // namespace layout
+} // namespace vsoc
+
diff --git a/common/vsoc/shm/circqueue.h b/common/vsoc/shm/circqueue.h
index 6e70c48..e841bbf 100644
--- a/common/vsoc/shm/circqueue.h
+++ b/common/vsoc/shm/circqueue.h
@@ -20,6 +20,7 @@
#include <atomic>
#include <cstdint>
+#include <sys/uio.h>
#include "common/vsoc/shm/base.h"
#include "common/vsoc/shm/lock.h"
@@ -154,6 +155,20 @@
intptr_t Write(RegionSignalingInterface* r, const char* buffer_in,
uint32_t bytes, bool non_blocking = false);
+ /**
+ * Writes the data referenced by the given iov scatter/gather array to the
+ * queue.
+ * If the number of bytes to be written exceeds the size of the queue
+ * -ENOSPC will be returned.
+ * If non_blocking is true and there is not enough free space on the queue to
+ * write all the data -EWOULDBLOCK will be returned.
+ */
+ intptr_t Writev(
+ RegionSignalingInterface *r,
+ const iovec *iov,
+ size_t iov_count,
+ bool non_blocking = false);
+
protected:
static_assert(CircularQueueBase<SizeLog2>::BufferSize >= MaxPacketSize,
"Buffer is too small to hold the maximum sized packet");
diff --git a/common/vsoc/shm/version.h b/common/vsoc/shm/version.h
index c1a82e2..7a4e329 100644
--- a/common/vsoc/shm/version.h
+++ b/common/vsoc/shm/version.h
@@ -110,7 +110,7 @@
const uint32_t version = 0;
}
// Three circular queues, each with a 1024 bytes buffer, a 32 bits spinlock and
-// two 32 bits inetgers
+// two 32 bits integers.
static const std::size_t InputEventsLayout_size = 3 * (1024 + 3 * 4);
} // namespace input_events
@@ -161,6 +161,17 @@
static const std::size_t E2EManagedTestRegionLayout_size = 4;
} // namespace e2e_test
+// Versioning information for audio_data_layout.h
+// Changes to these structures will affect only the audio_data region
+namespace audio_data {
+namespace {
+const uint32_t version = 0;
+}
+// One circular queue of with a 16KB buffer, a 32 bits spinlock and
+// two 32 bits integers.
+static const std::size_t AudioDataLayout_size = 16384 + 3 * 4;
+} // namespace audio_data
+
} // namespace version_info
} // namespace layout
} // namespace vsoc
diff --git a/guest/hals/audio/Android.mk b/guest/hals/audio/Android.mk
index 7991395..28733ff 100644
--- a/guest/hals/audio/Android.mk
+++ b/guest/hals/audio/Android.mk
@@ -25,11 +25,13 @@
LOCAL_MULTILIB := first
LOCAL_SHARED_LIBRARIES := \
+ libbase \
liblog \
libcutils \
cuttlefish_auto_resources \
libcuttlefish_fs \
- cuttlefish_time
+ cuttlefish_time \
+ vsoc_lib
LOCAL_HEADER_LIBRARIES := \
libhardware_headers
@@ -43,6 +45,7 @@
LOCAL_C_INCLUDES := \
device/google/cuttlefish_common \
+ device/google/cuttlefish_kernel \
$(VSOC_STLPORT_INCLUDES) \
frameworks/native/include/media/hardware \
$(call include-path-for, audio)
@@ -65,3 +68,25 @@
LOCAL_VENDOR_MODULE := true
include $(BUILD_SHARED_LIBRARY)
+
+################################################################################
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := record_audio
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := \
+ record_audio.cpp
+
+LOCAL_C_INCLUDES := \
+ device/google/cuttlefish_common \
+ device/google/cuttlefish_kernel \
+ frameworks/av/cmds/stagefright \
+
+LOCAL_SHARED_LIBRARIES := \
+ libbase \
+ vsoc_lib
+
+LOCAL_VENDOR_MODULE := true
+include $(BUILD_EXECUTABLE)
diff --git a/guest/hals/audio/record_audio.cpp b/guest/hals/audio/record_audio.cpp
new file mode 100644
index 0000000..6e9937d
--- /dev/null
+++ b/guest/hals/audio/record_audio.cpp
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "vsoc_audio_message.h"
+
+#include "common/vsoc/lib/audio_data_region_view.h"
+#include "common/vsoc/lib/circqueue_impl.h"
+
+#include "WaveWriter.h"
+
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <unistd.h>
+
+using AudioDataRegionView = vsoc::audio_data::AudioDataRegionView;
+using WaveWriter = android::WaveWriter;
+
+static void usage(const char *me) {
+ std::cerr << "usage: " << me << " -o filename [-v(erbose)]" << std::endl;
+ std::exit(1);
+}
+
+volatile bool gDone = false;
+static void SigIntHandler(int /* sig */) {
+ gDone = true;
+}
+
+int main(int argc, char **argv) {
+ const char *me = argv[0];
+
+ std::string outputPath;
+ bool verbose = false;
+
+ int res;
+ while ((res = getopt(argc, argv, "ho:v")) >= 0) {
+ switch (res) {
+ case 'o':
+ {
+ outputPath = optarg;
+ break;
+ }
+
+ case 'v' :
+ {
+ verbose = true;
+ break;
+ }
+
+ case '?':
+ case 'h':
+ default:
+ {
+ usage(me);
+ break;
+ }
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (outputPath.empty()) {
+ usage(me);
+ }
+
+ AudioDataRegionView *audio_data_rv = AudioDataRegionView::GetInstance();
+ audio_data_rv->Open();
+
+ /* std::unique_ptr<vsoc::RegionWorker> audio_worker = */
+ audio_data_rv->StartWorker();
+
+ std::unique_ptr<WaveWriter> writer;
+ int64_t frameCount = 0ll;
+
+ // The configuration the writer is setup for.
+ gce_audio_message writer_hdr;
+
+ uint8_t buffer[4096];
+
+ gDone = false;
+
+ struct sigaction act;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ act.sa_handler = SigIntHandler;
+
+ struct sigaction oact;
+ sigaction(SIGINT, &act, &oact);
+
+ while (!gDone) {
+ intptr_t res = audio_data_rv->data()->audio_queue.Read(
+ audio_data_rv,
+ reinterpret_cast<char *>(buffer),
+ sizeof(buffer));
+
+ if (res < 0) {
+ std::cerr << "CircularPacketQueue::Read returned " << res << std::endl;
+ continue;
+ }
+
+ CHECK_GE(static_cast<size_t>(res), sizeof(gce_audio_message));
+
+ gce_audio_message hdr;
+ std::memcpy(&hdr, buffer, sizeof(gce_audio_message));
+
+ if (hdr.message_type != gce_audio_message::DATA_SAMPLES) {
+ continue;
+ }
+
+ const size_t payloadSize = res - sizeof(gce_audio_message);
+
+ if (verbose) {
+ std::cout
+ << "stream "
+ << hdr.stream_number
+ << ", frame "
+ << hdr.frame_num
+ << ", rate "
+ << hdr.frame_rate
+ << ", channel_mask "
+ << hdr.channel_mask
+ << ", format "
+ << hdr.format
+ << ", payload_size "
+ << payloadSize
+ << std::endl;
+ }
+
+ if (!writer) {
+ const size_t numChannels = hdr.frame_size / sizeof(int16_t);
+
+ writer.reset(
+ new WaveWriter(outputPath.c_str(), numChannels, hdr.frame_rate));
+
+ frameCount = hdr.frame_num;
+ writer_hdr = hdr;
+ } else if (writer_hdr.frame_size != hdr.frame_size
+ || writer_hdr.frame_rate != hdr.frame_rate
+ || writer_hdr.stream_number != hdr.stream_number) {
+ std::cerr << "Audio configuration changed. Aborting." << std::endl;
+ break;
+ }
+
+ int64_t framesMissing = hdr.frame_num - frameCount;
+ if (framesMissing > 0) {
+ // TODO(andih): Insert silence here, if necessary.
+ }
+
+ frameCount = hdr.frame_num;
+
+ writer->Append(&buffer[sizeof(gce_audio_message)], payloadSize);
+ }
+
+ std::cout << "Done." << std::endl;
+
+ return 0;
+}
diff --git a/guest/hals/audio/vsoc_audio.cpp b/guest/hals/audio/vsoc_audio.cpp
index cfd7017..67ff28f 100644
--- a/guest/hals/audio/vsoc_audio.cpp
+++ b/guest/hals/audio/vsoc_audio.cpp
@@ -15,6 +15,7 @@
*/
#include "guest/hals/audio/audio_hal.h"
+#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
@@ -28,6 +29,7 @@
#include "common/libs/fs/shared_select.h"
#include "common/libs/threads/cuttlefish_thread.h"
#include "common/libs/threads/thunkers.h"
+#include "common/vsoc/lib/circqueue_impl.h"
#include "guest/hals/audio/vsoc_audio.h"
#include "guest/hals/audio/vsoc_audio_input_stream.h"
#include "guest/hals/audio/vsoc_audio_output_stream.h"
@@ -63,22 +65,10 @@
delete it->second;
}
}
- // Make certain that the listener thread wakes up
- cvd::SharedFD temp_client =
- cvd::SharedFD::SocketSeqPacketClient(
- gce_audio_message::kAudioHALSocketName);
- uint64_t dummy_val = 1;
- terminate_listener_thread_event_->Write(&dummy_val, sizeof dummy_val);
- pthread_join(listener_thread_, NULL);
delete this;
return 0;
}
-cvd::SharedFD GceAudio::GetAudioFd() {
- LockGuard<Mutex> guard(lock_);
- return audio_data_socket_;
-}
-
size_t GceAudio::GetInputBufferSize(const audio_config*) const {
return IN_BUFFER_BYTES;
}
@@ -223,12 +213,20 @@
return 0;
}
-ssize_t GceAudio::SendMsg(const msghdr& msg, int flags) {
- cvd::SharedFD fd = GetAudioFd();
- if (!fd->IsOpen()) {
- return 0;
- }
- return fd->SendMsg(&msg, flags);
+ssize_t GceAudio::SendMsg(const msghdr& msg, int /* flags */) {
+ intptr_t res = audio_data_rv_->data()->audio_queue.Writev(
+ audio_data_rv_,
+ msg.msg_iov,
+ msg.msg_iovlen,
+ true /* non_blocking */);
+
+ if (res < 0) {
+ ALOGV("GceAudio::%s: CircularPacketQueue::Write returned %" PRIiPTR,
+ __FUNCTION__,
+ res);
+ }
+
+ return static_cast<ssize_t>(res);
}
ssize_t GceAudio::SendStreamUpdate(
@@ -283,94 +281,6 @@
return 0;
}
-void* GceAudio::Listener() {
- // TODO(ghartman): Consider tightening the mode on this later.
- audio_listener_socket_ = cvd::SharedFD::SocketSeqPacketServer(
- gce_audio_message::kAudioHALSocketName, 0777);
- if (!audio_listener_socket_->IsOpen()) {
- ALOGE("GceAudio::%s: Could not listen for audio connections. (%s).",
- __FUNCTION__, audio_listener_socket_->StrError());
- return NULL;
- }
- ALOGI("GceAudio::%s: Listening for audio connections at %s",
- __FUNCTION__, gce_audio_message::kAudioHALSocketName);
- remoter_request_packet announce;
- remoter_request_packet_init(&announce, kRemoterHALReady, 0);
- announce.send_response = 0;
- strncpy(announce.params.hal_ready_params.unix_socket,
- gce_audio_message::kAudioHALSocketName,
- sizeof(announce.params.hal_ready_params.unix_socket));
- AutoCloseFileDescriptor remoter_socket(remoter_connect());
- if (remoter_socket.IsError()) {
- ALOGI("GceAudio::%s: Couldn't connect to remoter to register HAL (%s).",
- __FUNCTION__, strerror(errno));
- } else {
- int err = remoter_do_single_request_with_socket(
- remoter_socket, &announce, NULL);
- if (err == -1) {
- ALOGI("GceAudio::%s: HAL registration failed after connect (%s).",
- __FUNCTION__, strerror(errno));
- } else {
- ALOGI("GceAudio::%s: HAL registered with the remoter", __FUNCTION__);
- }
- }
- while (true) {
- // Poll for new connections or the terminatation event.
- // The listener is non-blocking. We send to at most one client. If a new
- // client comes in disconnect the old one.
- cvd::SharedFDSet fd_set;
- fd_set.Set(audio_listener_socket_);
- fd_set.Set(terminate_listener_thread_event_);
- if (cvd::Select(&fd_set, NULL, NULL, NULL) <= 0) {
- // There's no timeout, so 0 shouldn't happen.
- ALOGE("GceAudio::%s: Error using shared Select", __FUNCTION__);
- break;
- }
- if (fd_set.IsSet(terminate_listener_thread_event_)) {
- break;
- }
- LOG_FATAL_IF(fd_set.IsSet(audio_listener_socket_),
- "No error in Select() but nothing ready to read");
- cvd::SharedFD fd = cvd::SharedFD::Accept(
- *audio_listener_socket_);
- if (!fd->IsOpen()) {
- continue;
- }
- std::list<gce_audio_message> streams;
- {
- LockGuard<Mutex> guard(lock_);
- // Do not do I/O while holding the lock. It could block the HAL
- // implementation.
- // Register the fd before dropping the lock to ensure that every
- // active stream will appear when we first connect.
- // Some output streams may appear twice if an open is active
- // during the connect.
- audio_data_socket_ = fd;
- for (std::list<GceAudioOutputStream*>::iterator it = output_list_.begin();
- it != output_list_.end(); ++it) {
- streams.push_back((*it)->GetStreamDescriptor(
- gce_audio_message::OPEN_OUTPUT_STREAM));
- }
- for (input_map_t::iterator it = input_map_.begin();
- it != input_map_.end(); ++it) {
- streams.push_back(it->second->GetStreamDescriptor(
- it->first, gce_audio_message::OPEN_INPUT_STREAM));
- }
- }
- for (std::list<gce_audio_message>::iterator it = streams.begin();
- it != streams.end(); ++it) {
- // We're willing to block because this is independent of the HAL
- // implementation. We also don't want to forget to mention the input
- // streams.
- if (SendStreamUpdate(*it, 0) < 0) {
- ALOGE("GceAudio::%s: Failed to announce open stream (%s)",
- __FUNCTION__, fd->StrError());
- }
- }
- }
- return NULL;
-}
-
int GceAudio::Open(const hw_module_t* module, const char* name,
hw_device_t** device) {
D("GceAudio::%s", __FUNCTION__);
@@ -382,13 +292,11 @@
}
GceAudio* rval = new GceAudio;
- int err = pthread_create(
- &rval->listener_thread_, NULL,
- AudioThreadThunker<void*()>::call<&GceAudio::Listener>, rval);
- if (err) {
- ALOGE("GceAudio::%s: Unable to start listener thread (%s)", __FUNCTION__,
- strerror(err));
- }
+
+ rval->audio_data_rv_ = AudioDataRegionView::GetInstance();
+ rval->audio_data_rv_->Open();
+ rval->audio_worker_ = rval->audio_data_rv_->StartWorker();
+
rval->common.tag = HARDWARE_DEVICE_TAG;
rval->common.version = version_;
rval->common.module = const_cast<hw_module_t *>(module);
diff --git a/guest/hals/audio/vsoc_audio.h b/guest/hals/audio/vsoc_audio.h
index 4022888..6a6e0e6 100644
--- a/guest/hals/audio/vsoc_audio.h
+++ b/guest/hals/audio/vsoc_audio.h
@@ -20,6 +20,7 @@
#include "common/libs/fs/shared_fd.h"
#include "common/libs/threads/cuttlefish_thread.h"
+#include "common/vsoc/lib/audio_data_region_view.h"
#include "guest/hals/audio/audio_hal.h"
#include "guest/hals/audio/vsoc_audio_input_stream.h"
#include "guest/hals/audio/vsoc_audio_message.h"
@@ -46,10 +47,6 @@
return mic_muted_;
}
- // Retrieves the SharedFD of the process accepting audio data.
- // Returns a non-open fd if no process is listening (the normal case).
- cvd::SharedFD GetAudioFd();
-
// Send a message to the connected streamer.
// Returns:
// 0 if there is no streamer.
@@ -211,8 +208,6 @@
private:
- // Main routine for a thread that listens for incoming streamer connections.
- void* Listener();
// HAL 3.0 modifies the signatures of OpenInputStream and OpenOutputStream.
// We don't want to fork the implementation, and we don't want #ifdefs all
// over the code. The current implementation defines OpenInputStream and
@@ -270,19 +265,12 @@
static const unsigned int version_ = AUDIO_DEVICE_API_VERSION_1_0;
#endif
- // Thread to handle new connections.
- pthread_t listener_thread_;
- // Event to indicate that the listener thread should terminate.
- cvd::SharedFD terminate_listener_thread_event_;
- // The listener socket, which is polled for new connections.
- // TODO(ghartman): Consider using a thread.
- cvd::SharedFD audio_listener_socket_;
+ using AudioDataRegionView = vsoc::audio_data::AudioDataRegionView;
+ AudioDataRegionView *audio_data_rv_ = NULL;
+ std::unique_ptr<vsoc::RegionWorker> audio_worker_;
+
// Lock to protect the data below.
mutable cvd::Mutex lock_;
- // The data socket for the current streamer. Typically -1.
- // The behavior of the HAL should not be affected by the presence or absence
- // of the streamer.
- cvd::SharedFD audio_data_socket_;
// State that is managed at the device level.
float voice_volume_;
float master_volume_;
@@ -307,7 +295,6 @@
GceAudio() :
audio_hw_device(),
- terminate_listener_thread_event_(cvd::SharedFD::Event()),
voice_volume_(0.0),
master_volume_(0.0),
master_muted_(false),
diff --git a/host/config/vsoc_mem.json b/host/config/vsoc_mem.json
index 7cdb794..f9cbc36 100644
--- a/host/config/vsoc_mem.json
+++ b/host/config/vsoc_mem.json
@@ -206,6 +206,23 @@
"host_to_guest_signal_table" : {
"num_nodes_lg2" : 1
}
+ },
+
+ {
+ "device_name" : "audio_data",
+ "__comment" : "Write audio HAL output data to ringbuffer",
+ "current_version" : 0,
+ "min_compatible_version" : 0,
+ "region_size": 20480,
+
+ "guest_to_host_signal_table" : {
+ "__comment" : "sizeof each node is based on common/libs/shm_compatible/lock.h",
+ "num_nodes_lg2" : 2
+ },
+
+ "host_to_guest_signal_table" : {
+ "num_nodes_lg2" : 2
+ }
}
]
}