summaryrefslogtreecommitdiff
path: root/audio_proxy
diff options
context:
space:
mode:
authoryucliu <yucliu@google.com>2022-02-15 21:06:30 -0800
committerYuchen Liu <yucliu@google.com>2022-03-14 23:24:05 +0000
commite448052c6bde4dbacba0fe2df045ed56cf2a73fd (patch)
tree07efb1102de85af474a149e9a22af231a5444cd9 /audio_proxy
parent075557a388a9e246783232d8d6d9d77c4460e361 (diff)
downloadatv-e448052c6bde4dbacba0fe2df045ed56cf2a73fd.tar.gz
[AudioProxy] Different stream use different latency/buffer size
Change the command line argument so that different stream now can have different latency and buffer sizes. Bug: 177944032 Test: Unit test. On device test. Change-Id: I006154420c5c607d85ac637fb0e741c665dda513 (cherry picked from commit 9ae96df5f5c64a8826d6bf3e5788f9c8d05b6014)
Diffstat (limited to 'audio_proxy')
-rw-r--r--audio_proxy/service/Android.bp8
-rw-r--r--audio_proxy/service/DeviceImpl.cpp25
-rw-r--r--audio_proxy/service/DeviceImpl.h7
-rw-r--r--audio_proxy/service/DevicesFactoryImpl.cpp8
-rw-r--r--audio_proxy/service/DevicesFactoryImpl.h2
-rw-r--r--audio_proxy/service/ServiceConfig.cpp94
-rw-r--r--audio_proxy/service/ServiceConfig.h21
-rw-r--r--audio_proxy/service/ServiceConfigTest.cpp61
-rw-r--r--audio_proxy/service/device.google.atv.audio_proxy@5.1-service.rc5
-rw-r--r--audio_proxy/service/device.google.atv.audio_proxy@6.0-service.rc5
-rw-r--r--audio_proxy/service/device.google.atv.audio_proxy@7.0-service.rc5
-rw-r--r--audio_proxy/service/device.google.atv.audio_proxy@7.1-service.rc5
-rw-r--r--audio_proxy/service/main.cpp47
13 files changed, 221 insertions, 72 deletions
diff --git a/audio_proxy/service/Android.bp b/audio_proxy/service/Android.bp
index 2c219c6..711add8 100644
--- a/audio_proxy/service/Android.bp
+++ b/audio_proxy/service/Android.bp
@@ -27,6 +27,7 @@ cc_library_static {
host_supported: true,
srcs: [
"RingBufferUtil.cpp",
+ "ServiceConfig.cpp",
],
shared_libs: [
"libbase",
@@ -180,9 +181,16 @@ cc_test {
srcs: [
"RingBufferUtilTest.cpp",
+ "ServiceConfigTest.cpp",
],
static_libs: [
"audio_proxy_service_util",
+ "libbase",
"libgtest",
],
+
+ cflags: [
+ // Suppress the warning to make ServiceConfigTest easier.
+ "-Wno-writable-strings",
+ ],
}
diff --git a/audio_proxy/service/DeviceImpl.cpp b/audio_proxy/service/DeviceImpl.cpp
index 4684dec..75d411a 100644
--- a/audio_proxy/service/DeviceImpl.cpp
+++ b/audio_proxy/service/DeviceImpl.cpp
@@ -23,6 +23,7 @@
#include "AidlTypes.h"
#include "BusOutputStream.h"
#include "BusStreamProvider.h"
+#include "ServiceConfig.h"
#include "StreamOutImpl.h"
using namespace ::android::hardware::audio::common::CPP_VERSION;
@@ -70,10 +71,8 @@ AidlAudioConfig toAidlAudioConfig(const AudioConfig& hidl_config) {
} // namespace
DeviceImpl::DeviceImpl(BusStreamProvider& busStreamProvider,
- uint32_t bufferSizeMs, uint32_t latencyMs)
- : mBusStreamProvider(busStreamProvider),
- mBufferSizeMs(bufferSizeMs),
- mLatencyMs(latencyMs) {}
+ const ServiceConfig& serviceConfig)
+ : mBusStreamProvider(busStreamProvider), mServiceConfig(serviceConfig) {}
// Methods from ::android::hardware::audio::V5_0::IDevice follow.
Return<Result> DeviceImpl::initCheck() { return Result::OK; }
@@ -124,6 +123,12 @@ Return<void> DeviceImpl::openOutputStreamImpl(
return Void();
}
+ const auto configIt = mServiceConfig.streams.find(device.address.id());
+ if (configIt == mServiceConfig.streams.end()) {
+ _hidl_cb(Result::INVALID_ARGUMENTS, nullptr, {});
+ return Void();
+ }
+
std::optional<AidlAudioConfig> aidlConfig = toAidlAudioConfig(config.base);
if (!aidlConfig) {
DCHECK(false);
@@ -148,7 +153,8 @@ Return<void> DeviceImpl::openOutputStreamImpl(
static_cast<int32_t>(outputFlags));
DCHECK(busOutputStream);
auto streamOut = sp<StreamOutImpl>::make(std::move(busOutputStream),
- mBufferSizeMs, mLatencyMs);
+ configIt->second.bufferSizeMs,
+ configIt->second.latencyMs);
mBusStreamProvider.onStreamOutCreated(streamOut);
_hidl_cb(Result::OK, streamOut, config);
return Void();
@@ -180,13 +186,20 @@ Return<void> DeviceImpl::openOutputStream(int32_t ioHandle,
hidl_bitfield<AudioOutputFlag> flags,
const SourceMetadata& sourceMetadata,
openOutputStream_cb _hidl_cb) {
+ const auto configIt = mServiceConfig.streams.find(device.busAddress);
+ if (configIt == mServiceConfig.streams.end()) {
+ _hidl_cb(Result::INVALID_ARGUMENTS, nullptr, {});
+ return Void();
+ }
+
std::shared_ptr<BusOutputStream> busOutputStream =
mBusStreamProvider.openOutputStream(device.busAddress,
toAidlAudioConfig(config),
static_cast<int32_t>(flags));
DCHECK(busOutputStream);
auto streamOut = sp<StreamOutImpl>::make(std::move(busOutputStream),
- mBufferSizeMs, mLatencyMs);
+ configIt->second.bufferSizeMs,
+ configIt->second.latencyMs);
mBusStreamProvider.onStreamOutCreated(streamOut);
_hidl_cb(Result::OK, streamOut, config);
return Void();
diff --git a/audio_proxy/service/DeviceImpl.h b/audio_proxy/service/DeviceImpl.h
index 44ad3b0..ffe3f88 100644
--- a/audio_proxy/service/DeviceImpl.h
+++ b/audio_proxy/service/DeviceImpl.h
@@ -54,6 +54,7 @@ using ::android::hardware::audio::common::CPP_VERSION::AudioOutputFlag;
#endif
class BusStreamProvider;
+struct ServiceConfig;
#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
class DeviceImpl : public android::hardware::audio::V7_1::IDevice {
@@ -61,8 +62,7 @@ class DeviceImpl : public android::hardware::audio::V7_1::IDevice {
class DeviceImpl : public IDevice {
#endif
public:
- DeviceImpl(BusStreamProvider& busStreamProvider, uint32_t bufferSizeMs,
- uint32_t latencyMs);
+ DeviceImpl(BusStreamProvider& busStreamProvider, const ServiceConfig& config);
// Methods from ::android::hardware::audio::V5_0::IDevice follow.
Return<Result> initCheck() override;
@@ -154,8 +154,7 @@ class DeviceImpl : public IDevice {
#endif
BusStreamProvider& mBusStreamProvider;
- const uint32_t mBufferSizeMs;
- const uint32_t mLatencyMs;
+ const ServiceConfig& mServiceConfig;
std::set<AudioPatchHandle> mAudioPatchHandles;
};
diff --git a/audio_proxy/service/DevicesFactoryImpl.cpp b/audio_proxy/service/DevicesFactoryImpl.cpp
index a93ad4c..c5575a5 100644
--- a/audio_proxy/service/DevicesFactoryImpl.cpp
+++ b/audio_proxy/service/DevicesFactoryImpl.cpp
@@ -31,9 +31,7 @@ Return<void> DevicesFactoryImpl::openDevice(const hidl_string& device,
openDevice_cb _hidl_cb) {
if (device == mConfig.name) {
LOG(INFO) << "Audio Device was opened: " << device;
- _hidl_cb(Result::OK,
- new DeviceImpl(mBusStreamProvider, mConfig.bufferSizeMs,
- mConfig.latencyMs));
+ _hidl_cb(Result::OK, new DeviceImpl(mBusStreamProvider, mConfig));
} else {
_hidl_cb(Result::INVALID_ARGUMENTS, nullptr);
}
@@ -53,9 +51,7 @@ Return<void> DevicesFactoryImpl::openDevice_7_1(const hidl_string& device,
openDevice_7_1_cb _hidl_cb) {
if (device == mConfig.name) {
LOG(INFO) << "Audio Device was opened: " << device;
- _hidl_cb(Result::OK,
- new DeviceImpl(mBusStreamProvider, mConfig.bufferSizeMs,
- mConfig.latencyMs));
+ _hidl_cb(Result::OK, new DeviceImpl(mBusStreamProvider, mConfig));
} else {
_hidl_cb(Result::INVALID_ARGUMENTS, nullptr);
}
diff --git a/audio_proxy/service/DevicesFactoryImpl.h b/audio_proxy/service/DevicesFactoryImpl.h
index 560692e..d9326eb 100644
--- a/audio_proxy/service/DevicesFactoryImpl.h
+++ b/audio_proxy/service/DevicesFactoryImpl.h
@@ -53,7 +53,7 @@ class DevicesFactoryImpl : public IDevicesFactory {
private:
BusStreamProvider& mBusStreamProvider;
- const ServiceConfig mConfig;
+ const ServiceConfig& mConfig;
};
} // namespace service
diff --git a/audio_proxy/service/ServiceConfig.cpp b/audio_proxy/service/ServiceConfig.cpp
new file mode 100644
index 0000000..61f40aa
--- /dev/null
+++ b/audio_proxy/service/ServiceConfig.cpp
@@ -0,0 +1,94 @@
+// Copyright (C) 2022 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 "ServiceConfig.h"
+
+#include <android-base/parseint.h>
+#include <android-base/strings.h>
+#include <getopt.h>
+
+#include <utility>
+#include <vector>
+
+namespace audio_proxy::service {
+namespace {
+std::pair<std::string, StreamConfig> parseStreamConfig(const char* optarg) {
+ std::vector<std::string> tokens = android::base::Split(optarg, ":");
+ if (tokens.size() != 3) {
+ return {};
+ }
+
+ StreamConfig config;
+ if (!android::base::ParseUint(tokens[1].c_str(), &config.bufferSizeMs)) {
+ return {};
+ }
+
+ if (!android::base::ParseUint(tokens[2].c_str(), &config.latencyMs)) {
+ return {};
+ }
+
+ return {tokens[0], config};
+}
+} // namespace
+
+std::optional<ServiceConfig> parseServiceConfigFromCommandLine(int argc,
+ char** argv) {
+ // $command --name service_name
+ // --stream address1:buffer_size:latency
+ // --stream address2:buffer_size:latency
+ static option options[] = {
+ {"name", required_argument, nullptr, 'n'},
+ {"stream", required_argument, nullptr, 's'},
+ {nullptr, 0, nullptr, 0},
+ };
+
+ // Reset, this is useful in unittest.
+ optind = 0;
+
+ ServiceConfig config;
+ int val = 0;
+ while ((val = getopt_long(argc, argv, "n:s:", options, nullptr)) != -1) {
+ switch (val) {
+ case 'n':
+ config.name = optarg;
+ break;
+
+ case 's': {
+ std::pair<std::string, StreamConfig> streamConfig =
+ parseStreamConfig(optarg);
+ if (streamConfig.first.empty()) {
+ return std::nullopt;
+ }
+
+ auto it = config.streams.emplace(std::move(streamConfig));
+ if (!it.second) {
+ return std::nullopt;
+ }
+
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+
+ if (config.name.empty() || config.streams.empty()) {
+ return std::nullopt;
+ }
+
+ return config;
+}
+
+} // namespace audio_proxy::service \ No newline at end of file
diff --git a/audio_proxy/service/ServiceConfig.h b/audio_proxy/service/ServiceConfig.h
index 837b47c..f3de742 100644
--- a/audio_proxy/service/ServiceConfig.h
+++ b/audio_proxy/service/ServiceConfig.h
@@ -16,21 +16,32 @@
#include <stdint.h>
+#include <map>
+#include <optional>
#include <string>
namespace audio_proxy::service {
+struct StreamConfig {
+ // Buffer size in milliseconds, as defined by IStream::getBufferSize.
+ uint32_t bufferSizeMs;
+
+ // Latency in milliseconds, as defined by IStreamOut::getLatency.
+ uint32_t latencyMs;
+};
+
// Global configurations for the audio HAL service and AudioProxy service.
struct ServiceConfig {
// Name of the service. It will be used to identify the audio HAL service and
// AudioProxy service.
std::string name;
- // Buffer size in milliseconds, as defined by IStream::getBufferSize.
- uint32_t bufferSizeMs = 0;
-
- // Latency in milliseconds, as defined by IStreamOut::getLatency.
- uint32_t latencyMs = 0;
+ // Supported stream configs. Key is the address of the stream. Value is the
+ // config.
+ std::map<std::string, StreamConfig> streams;
};
+std::optional<ServiceConfig> parseServiceConfigFromCommandLine(int argc,
+ char** argv);
+
} // namespace audio_proxy::service \ No newline at end of file
diff --git a/audio_proxy/service/ServiceConfigTest.cpp b/audio_proxy/service/ServiceConfigTest.cpp
new file mode 100644
index 0000000..e796464
--- /dev/null
+++ b/audio_proxy/service/ServiceConfigTest.cpp
@@ -0,0 +1,61 @@
+// Copyright (C) 2022 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 <gtest/gtest.h>
+
+#include "ServiceConfig.h"
+
+using namespace audio_proxy::service;
+
+TEST(ServiceConfigTest, GoodConfig) {
+ char* argv[] = {"command", "--name", "service", "--stream", "A:1:2"};
+ auto config =
+ parseServiceConfigFromCommandLine(sizeof(argv) / sizeof(argv[0]), argv);
+
+ ASSERT_TRUE(config);
+ EXPECT_EQ(config->name, "service");
+ EXPECT_EQ(config->streams.size(), 1);
+ EXPECT_EQ(config->streams.begin()->first, "A");
+ EXPECT_EQ(config->streams.begin()->second.bufferSizeMs, 1u);
+ EXPECT_EQ(config->streams.begin()->second.latencyMs, 2u);
+}
+
+TEST(ServiceConfigTest, MultipleStreams) {
+ char* argv[] = {"command", "--name", "service", "--stream",
+ "A:1:2", "--stream", "B:3:4"};
+ auto config =
+ parseServiceConfigFromCommandLine(sizeof(argv) / sizeof(argv[0]), argv);
+
+ ASSERT_TRUE(config);
+ EXPECT_EQ(config->name, "service");
+ EXPECT_EQ(config->streams.size(), 2);
+
+ ASSERT_TRUE(config->streams.count("A"));
+ const auto& streamA = config->streams["A"];
+ EXPECT_EQ(streamA.bufferSizeMs, 1u);
+ EXPECT_EQ(streamA.latencyMs, 2u);
+
+ ASSERT_TRUE(config->streams.count("B"));
+ const auto& streamB = config->streams["B"];
+ EXPECT_EQ(streamB.bufferSizeMs, 3u);
+ EXPECT_EQ(streamB.latencyMs, 4u);
+}
+
+TEST(ServiceConfigTest, NoStreamConfig) {
+ char* argv[] = {"command", "--name", "service"};
+ auto config =
+ parseServiceConfigFromCommandLine(sizeof(argv) / sizeof(argv[0]), argv);
+
+ EXPECT_FALSE(config);
+}
diff --git a/audio_proxy/service/device.google.atv.audio_proxy@5.1-service.rc b/audio_proxy/service/device.google.atv.audio_proxy@5.1-service.rc
index f639d21..5ce6140 100644
--- a/audio_proxy/service/device.google.atv.audio_proxy@5.1-service.rc
+++ b/audio_proxy/service/device.google.atv.audio_proxy@5.1-service.rc
@@ -1,4 +1,7 @@
-service audio_proxy_service /vendor/bin/hw/device.google.atv.audio_proxy@5.1-service --service_name mediashell --buffer_size_ms 40 --latency_ms 40
+service audio_proxy_service /vendor/bin/hw/device.google.atv.audio_proxy@5.1-service \
+ --name mediashell \
+ --stream MEDIASHELL_AUDIO_DEVICE_ADDR:40:200 \
+ --stream MEDIASHELL_MIXER_DEVICE_ADDR:40:40
class hal
user system
group system
diff --git a/audio_proxy/service/device.google.atv.audio_proxy@6.0-service.rc b/audio_proxy/service/device.google.atv.audio_proxy@6.0-service.rc
index fc39baf..e0a9371 100644
--- a/audio_proxy/service/device.google.atv.audio_proxy@6.0-service.rc
+++ b/audio_proxy/service/device.google.atv.audio_proxy@6.0-service.rc
@@ -1,4 +1,7 @@
-service audio_proxy_service /vendor/bin/hw/device.google.atv.audio_proxy@6.0-service --service_name mediashell --buffer_size_ms 40 --latency_ms 40
+service audio_proxy_service /vendor/bin/hw/device.google.atv.audio_proxy@6.0-service \
+ --name mediashell \
+ --stream MEDIASHELL_AUDIO_DEVICE_ADDR:40:200 \
+ --stream MEDIASHELL_MIXER_DEVICE_ADDR:40:40
class hal
user system
group system
diff --git a/audio_proxy/service/device.google.atv.audio_proxy@7.0-service.rc b/audio_proxy/service/device.google.atv.audio_proxy@7.0-service.rc
index 0335031..d8d2298 100644
--- a/audio_proxy/service/device.google.atv.audio_proxy@7.0-service.rc
+++ b/audio_proxy/service/device.google.atv.audio_proxy@7.0-service.rc
@@ -1,4 +1,7 @@
-service audio_proxy_service /vendor/bin/hw/device.google.atv.audio_proxy@7.0-service --service_name mediashell --buffer_size_ms 40 --latency_ms 40
+service audio_proxy_service /vendor/bin/hw/device.google.atv.audio_proxy@7.0-service \
+ --name mediashell \
+ --stream MEDIASHELL_AUDIO_DEVICE_ADDR:40:200 \
+ --stream MEDIASHELL_MIXER_DEVICE_ADDR:40:40
class hal
user system
group system
diff --git a/audio_proxy/service/device.google.atv.audio_proxy@7.1-service.rc b/audio_proxy/service/device.google.atv.audio_proxy@7.1-service.rc
index 77051e6..6490f71 100644
--- a/audio_proxy/service/device.google.atv.audio_proxy@7.1-service.rc
+++ b/audio_proxy/service/device.google.atv.audio_proxy@7.1-service.rc
@@ -1,4 +1,7 @@
-service audio_proxy_service /vendor/bin/hw/device.google.atv.audio_proxy@7.1-service --service_name mediashell --buffer_size_ms 40 --latency_ms 40
+service audio_proxy_service /vendor/bin/hw/device.google.atv.audio_proxy@7.1-service \
+ --name mediashell \
+ --stream MEDIASHELL_AUDIO_DEVICE_ADDR:40:200 \
+ --stream MEDIASHELL_MIXER_DEVICE_ADDR:40:40
class hal
user system
group system
diff --git a/audio_proxy/service/main.cpp b/audio_proxy/service/main.cpp
index 4e4eced..9c16a90 100644
--- a/audio_proxy/service/main.cpp
+++ b/audio_proxy/service/main.cpp
@@ -13,10 +13,8 @@
// limitations under the License.
#include <android-base/logging.h>
-#include <android-base/parseint.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
-#include <getopt.h>
#include <hidl/HidlTransportSupport.h>
#include <optional>
@@ -24,56 +22,13 @@
#include "AudioProxyError.h"
#include "AudioProxyImpl.h"
#include "DevicesFactoryImpl.h"
+#include "ServiceConfig.h"
using android::sp;
using android::status_t;
using namespace audio_proxy::service;
-namespace {
-
-std::optional<ServiceConfig> parseServiceConfigFromCommandLine(int argc,
- char** argv) {
- ServiceConfig config;
- static option options[] = {
- {"service_name", required_argument, nullptr, 's'},
- {"buffer_size_ms", required_argument, nullptr, 'b'},
- {"latency_ms", required_argument, nullptr, 'l'},
- {nullptr, 0, nullptr, 0},
- };
-
- int val = 0;
- while ((val = getopt_long(argc, argv, "s:b:l:", options, nullptr)) != -1) {
- switch (val) {
- case 's':
- config.name = optarg;
- break;
- case 'b':
- if (!android::base::ParseUint(optarg, &config.bufferSizeMs)) {
- return std::nullopt;
- }
- break;
- case 'l':
- if (!android::base::ParseUint(optarg, &config.latencyMs)) {
- return std::nullopt;
- }
- break;
-
- default:
- break;
- }
- }
-
- if (config.name.empty() || config.bufferSizeMs == 0 ||
- config.latencyMs == 0) {
- return std::nullopt;
- }
-
- return config;
-}
-
-} // namespace
-
int main(int argc, char** argv) {
auto config = parseServiceConfigFromCommandLine(argc, argv);
if (!config) {