summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2021-04-10 01:01:08 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2021-04-10 01:01:08 +0000
commitca6e3c731fc689c689a5c7ec0952a5a826e29f05 (patch)
treeebca1ed7bd934a7b6073b2777636df8729b85e1d
parentf36af165a57540518041d7f8a8c9a73d557cf7aa (diff)
parentb0f818e016c66f8fbef006aad07a3f4504d77704 (diff)
downloadtrout-android11-qpr3-s1-release.tar.gz
Change-Id: Ia6da2122244a09dca53cfe2b8e9ba93e2a4e626a
-rw-r--r--hal/audio/6.0/audio_hw.c83
-rw-r--r--tests/hal/vehicle/2.0/Android.bp32
-rw-r--r--tests/hal/vehicle/2.0/GrpcServer_test.cpp162
3 files changed, 253 insertions, 24 deletions
diff --git a/hal/audio/6.0/audio_hw.c b/hal/audio/6.0/audio_hw.c
index 317d77e..f63940d 100644
--- a/hal/audio/6.0/audio_hw.c
+++ b/hal/audio/6.0/audio_hw.c
@@ -45,11 +45,16 @@
#define PCM_CARD 0
#define PCM_DEVICE 0
-#define OUT_PERIOD_MS 40
-#define OUT_PERIOD_COUNT 4
+#define DEFAULT_OUT_PERIOD_MS 40
+#define DEFAULT_OUT_PERIOD_COUNT 4
-#define IN_PERIOD_MS 40
-#define IN_PERIOD_COUNT 4
+#define DEFAULT_IN_PERIOD_MS 40
+#define DEFAULT_IN_PERIOD_COUNT 4
+
+static const char* PROP_KEY_OUT_PERIOD_MS = "ro.vendor.trout.audiohal.out_period_ms";
+static const char* PROP_KEY_OUT_PERIOD_COUNT = "ro.vendor.trout.audiohal.out_period_count";
+static const char* PROP_KEY_IN_PERIOD_MS = "ro.vendor.trout.audiohal.in_period_ms";
+static const char* PROP_KEY_IN_PERIOD_COUNT = "ro.vendor.trout.audiohal.in_period_count";
#define PI 3.14159265
#define TWO_PI (2*PI)
@@ -82,16 +87,47 @@ static const char * const AUDIO_ZONE_KEYWORD = "_audio_zone_";
static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state);
+static int get_out_period_ms() {
+ static int out_period_ms = -1;
+ if (out_period_ms == -1) {
+ out_period_ms = property_get_int32(PROP_KEY_OUT_PERIOD_MS, DEFAULT_OUT_PERIOD_MS);
+ }
+ return out_period_ms;
+}
+
+static int get_out_period_count() {
+ static int out_period_count = -1;
+ if (out_period_count == -1) {
+ out_period_count = property_get_int32(PROP_KEY_OUT_PERIOD_COUNT, DEFAULT_OUT_PERIOD_COUNT);
+ }
+ return out_period_count;
+}
+
+static int get_in_period_ms() {
+ static int in_period_ms = -1;
+ if (in_period_ms == -1) {
+ in_period_ms = property_get_int32(PROP_KEY_IN_PERIOD_MS, DEFAULT_IN_PERIOD_MS);
+ }
+ return in_period_ms;
+}
+
+static int get_in_period_count() {
+ static int in_period_count = -1;
+ if (in_period_count == -1) {
+ in_period_count = property_get_int32(PROP_KEY_IN_PERIOD_COUNT, DEFAULT_IN_PERIOD_COUNT);
+ }
+ return in_period_count;
+}
+
static struct pcm_config pcm_config_out = {
.channels = 2,
.rate = 0,
.period_size = 0,
- .period_count = OUT_PERIOD_COUNT,
.format = PCM_FORMAT_S16_LE,
.start_threshold = 0,
};
-static int get_int_value(const struct str_parms *str_parms, const char *key, int *return_value) {
+static int get_int_value(struct str_parms *str_parms, const char *key, int *return_value) {
char value[SIZE_OF_PARSE_BUFFER];
int results = str_parms_get_str(str_parms, key, value, SIZE_OF_PARSE_BUFFER);
if (results >= 0) {
@@ -111,7 +147,6 @@ static struct pcm_config pcm_config_in = {
.channels = 2,
.rate = 0,
.period_size = 0,
- .period_count = IN_PERIOD_COUNT,
.format = PCM_FORMAT_S16_LE,
.start_threshold = 0,
.stop_threshold = INT_MAX,
@@ -335,7 +370,7 @@ static void *out_write_worker(void *args) {
int frames = audio_vbuffer_read(&out->buffer, buffer, buffer_frames);
pthread_mutex_unlock(&out->lock);
- if (is_zone_selected_to_play(out->dev, zone_id)) {
+ if (is_zone_selected_to_play(&out->dev->device, zone_id)) {
int write_error = ext_pcm_write(ext_pcm, out->bus_address,
buffer, ext_pcm_frames_to_bytes(ext_pcm, frames));
if (write_error) {
@@ -485,7 +520,6 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer, si
static int out_get_presentation_position(const struct audio_stream_out *stream,
uint64_t *frames, struct timespec *timestamp) {
- int ret = -EINVAL;
if (stream == NULL || frames == NULL || timestamp == NULL) {
return -EINVAL;
}
@@ -654,12 +688,11 @@ static int refine_input_parameters(uint32_t *sample_rate, audio_format_t *format
static size_t get_input_buffer_size(uint32_t sample_rate, audio_format_t format,
audio_channel_mask_t channel_mask) {
size_t size;
- size_t device_rate;
int channel_count = popcount(channel_mask);
if (refine_input_parameters(&sample_rate, &format, &channel_mask) != 0)
return 0;
- size = sample_rate*IN_PERIOD_MS/1000;
+ size = sample_rate * get_in_period_ms() / 1000;
// Audioflinger expects audio buffers to be multiple of 16 frames
size = ((size + 15) / 16) * 16;
size *= sizeof(short) * channel_count;
@@ -895,7 +928,7 @@ static void *in_read_worker(void *args) {
return NULL;
}
-static bool address_has_tone_keyword(char * address) {
+static bool address_has_tone_keyword(const char * address) {
return strstr(address, TONE_ADDRESS_KEYWORD) != NULL;
}
@@ -927,7 +960,6 @@ static ssize_t in_read(struct audio_stream_in *stream, void *buffer, size_t byte
struct generic_stream_in *in = (struct generic_stream_in *)stream;
struct generic_audio_device *adev = in->dev;
const size_t frames = bytes / audio_stream_in_frame_size(stream);
- int ret = 0;
bool mic_mute = false;
size_t read_bytes = 0;
@@ -1101,7 +1133,7 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
memcpy(&out->req_config, config, sizeof(struct audio_config));
memcpy(&out->pcm_config, &pcm_config_out, sizeof(struct pcm_config));
out->pcm_config.rate = config->sample_rate;
- out->pcm_config.period_size = out->pcm_config.rate*OUT_PERIOD_MS/1000;
+ out->pcm_config.period_size = out->pcm_config.rate * get_out_period_ms() / 1000;
out->standby = true;
out->underrun_position = 0;
@@ -1134,9 +1166,8 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
out->enabled_channels = BOTH_CHANNELS;
if (address) {
- out->bus_address = calloc(strlen(address) + 1, sizeof(char));
- strncpy(out->bus_address, address, strlen(address));
- hashmapPut(adev->out_bus_stream_map, out->bus_address, out);
+ out->bus_address = strdup(address);
+ hashmapPut(adev->out_bus_stream_map, (void*)out->bus_address, out);
/* TODO: read struct audio_gain from audio_policy_configuration */
out->gain_stage = (struct audio_gain) {
.min_value = -3200,
@@ -1175,8 +1206,8 @@ static void adev_close_output_stream(struct audio_hw_device *dev,
audio_vbuffer_destroy(&out->buffer);
if (out->bus_address) {
- hashmapRemove(adev->out_bus_stream_map, out->bus_address);
- free(out->bus_address);
+ hashmapRemove(adev->out_bus_stream_map, (void*)out->bus_address);
+ free((void*)out->bus_address);
}
free(stream);
}
@@ -1279,7 +1310,7 @@ static void adev_close_input_stream(struct audio_hw_device *dev,
}
if (in->bus_address) {
- free(in->bus_address);
+ free((void*)in->bus_address);
}
pthread_mutex_destroy(&in->lock);
@@ -1295,8 +1326,8 @@ static void increase_next_tone_frequency(struct generic_audio_device *adev) {
}
static int create_or_fetch_tone_frequency(struct generic_audio_device *adev,
- char *address, int update_frequency) {
- int *frequency = hashmapGet(adev->in_bus_tone_frequency_map, address);
+ const char *address, int update_frequency) {
+ int *frequency = hashmapGet(adev->in_bus_tone_frequency_map, (void*)address);
if (frequency == NULL) {
frequency = calloc(1, sizeof(int));
*frequency = update_frequency;
@@ -1350,7 +1381,7 @@ static int adev_open_input_stream(struct audio_hw_device *dev,
memcpy(&in->req_config, config, sizeof(struct audio_config));
memcpy(&in->pcm_config, &pcm_config_in, sizeof(struct pcm_config));
in->pcm_config.rate = config->sample_rate;
- in->pcm_config.period_size = in->pcm_config.rate*IN_PERIOD_MS/1000;
+ in->pcm_config.period_size = in->pcm_config.rate * get_in_period_ms() / 1000;
in->stereo_to_mono_buf = NULL;
in->stereo_to_mono_buf_size = 0;
@@ -1401,7 +1432,7 @@ static int adev_set_audio_port_config(struct audio_hw_device *dev,
int ret = 0;
struct generic_audio_device *adev = (struct generic_audio_device *)dev;
const char *bus_address = config->ext.device.address;
- struct generic_stream_out *out = hashmapGet(adev->out_bus_stream_map, bus_address);
+ struct generic_stream_out *out = hashmapGet(adev->out_bus_stream_map, (void*)bus_address);
if (out) {
pthread_mutex_lock(&out->lock);
int gainIndex = (config->gain.values[0] - out->gain_stage.min_value) /
@@ -1527,6 +1558,10 @@ static int adev_open(const hw_module_t *module,
ALOGV("%s: exit", __func__);
goto unlock;
}
+
+ pcm_config_in.period_count = get_in_period_count();
+ pcm_config_out.period_count = get_out_period_count();
+
adev = calloc(1, sizeof(struct generic_audio_device));
pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
diff --git a/tests/hal/vehicle/2.0/Android.bp b/tests/hal/vehicle/2.0/Android.bp
new file mode 100644
index 0000000..3545255
--- /dev/null
+++ b/tests/hal/vehicle/2.0/Android.bp
@@ -0,0 +1,32 @@
+// Copyright (C) 2021 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.
+
+cc_test {
+ name: "android.hardware.automotive.vehicle@2.0-virtualization-server-unit-tests",
+ vendor: true,
+ defaults: ["vhal_v2_0_defaults"],
+ srcs: [
+ "GrpcServer_test.cpp",
+ ],
+ static_libs: [
+ "android.hardware.automotive.vehicle@2.0-virtualization-client-lib",
+ "android.hardware.automotive.vehicle@2.0-virtualization-grpc-server-lib",
+ ],
+ shared_libs: [
+ "libbase",
+ "libjsoncpp",
+ "libprotobuf-cpp-full",
+ "libgrpc++",
+ ],
+}
diff --git a/tests/hal/vehicle/2.0/GrpcServer_test.cpp b/tests/hal/vehicle/2.0/GrpcServer_test.cpp
new file mode 100644
index 0000000..ffa2f0b
--- /dev/null
+++ b/tests/hal/vehicle/2.0/GrpcServer_test.cpp
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2021 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 <chrono>
+#include <fstream>
+#include <thread>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include <android-base/file.h>
+#include <android/hardware/automotive/vehicle/2.0/types.h>
+#include <gtest/gtest.h>
+
+#include "GrpcVehicleClient.h"
+#include "GrpcVehicleServer.h"
+#include "Utils.h"
+#include "vhal_v2_0/VehicleUtils.h"
+
+namespace android::hardware::automotive::vehicle::V2_0::impl {
+
+class GrpcServerTest : public ::testing::Test {
+ public:
+ GrpcServerTest()
+ : mPowerStateSocketForTest(std::string(mTestTempDir.path) +
+ std::string("/power_state_socket_for_test_") +
+ std::to_string(getpid())),
+ mServerInfo({{GetTestCID(), 12345},
+ mPowerStateMarkerFileForTest.path,
+ mPowerStateSocketForTest}) {}
+
+ void SetUp() override {
+ mGrpcServer = makeGrpcVehicleServer(mServerInfo);
+
+ ASSERT_TRUE(GetGrpcServer() != nullptr);
+ GetGrpcServer()->Start();
+ }
+
+ void TearDown() override {
+ GetGrpcServer()->Stop().Wait();
+ mGrpcServer.reset();
+ }
+
+ static unsigned GetTestCID();
+
+ GrpcVehicleServer* GetGrpcServer() const { return mGrpcServer.get(); }
+
+ std::string GetGrpcServerUri() const { return mServerInfo.getServerUri(); }
+
+ std::string GetPowerStateSocketPath() const { return mPowerStateSocketForTest; }
+
+ std::string GetPowerStateMarkerFilePath() const {
+ return std::string(mPowerStateMarkerFileForTest.path);
+ }
+
+ void SendDummyValueFromServer();
+
+ void ExpectActivePropValueStreamNum(unsigned expected);
+
+ void WriteToPowerStateSocket(const std::string& val);
+
+ std::string ReadFromPowerStateMarkerFile() const;
+
+ private:
+ TemporaryDir mTestTempDir;
+ TemporaryFile mPowerStateMarkerFileForTest;
+
+ std::string mPowerStateSocketForTest{};
+
+ GrpcVehicleServerPtr mGrpcServer{nullptr};
+ VirtualizedVhalServerInfo mServerInfo;
+};
+
+unsigned GrpcServerTest::GetTestCID() {
+ // TODO(chenhaosjtuacm): find a way to get the local CID
+ return 1000;
+}
+
+void GrpcServerTest::SendDummyValueFromServer() {
+ VehiclePropValue value;
+ value.prop = toInt(VehicleProperty::INVALID);
+ GetGrpcServer()->onPropertyValueFromCar(value, false);
+}
+
+void GrpcServerTest::ExpectActivePropValueStreamNum(unsigned expected) {
+ // Force the server to refresh streams
+ SendDummyValueFromServer();
+
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+ EXPECT_EQ(GetGrpcServer()->NumOfActivePropertyValueStream(), expected);
+}
+
+void GrpcServerTest::WriteToPowerStateSocket(const std::string& val) {
+ int power_socket_fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ ASSERT_GE(power_socket_fd, 0);
+
+ struct sockaddr_un addr;
+ std::memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ std::string socket_path = GetPowerStateSocketPath();
+ std::strncpy(addr.sun_path, socket_path.c_str(), socket_path.length() + 1);
+
+ sync();
+
+ ASSERT_EQ(connect(power_socket_fd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)), 0);
+ EXPECT_EQ(write(power_socket_fd, val.c_str(), val.length()),
+ static_cast<ssize_t>(val.length()));
+ close(power_socket_fd);
+}
+
+std::string GrpcServerTest::ReadFromPowerStateMarkerFile() const {
+ std::ifstream stream(GetPowerStateMarkerFilePath());
+ std::string val;
+ stream >> val;
+ return val;
+}
+
+TEST_F(GrpcServerTest, PropertyValueStreamTest) {
+ ExpectActivePropValueStreamNum(0);
+ {
+ auto client1 = makeGrpcVehicleClient(GetGrpcServerUri());
+ ExpectActivePropValueStreamNum(1);
+ {
+ auto client2 = makeGrpcVehicleClient(GetGrpcServerUri());
+ ExpectActivePropValueStreamNum(2);
+ }
+ ExpectActivePropValueStreamNum(1);
+ }
+ ExpectActivePropValueStreamNum(0);
+}
+
+TEST_F(GrpcServerTest, PowerStateListenerTest) {
+ {
+ std::string power_state_str = "ok";
+ WriteToPowerStateSocket(power_state_str);
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+ EXPECT_EQ(ReadFromPowerStateMarkerFile(), power_state_str);
+ }
+
+ {
+ std::string power_state_str = "shutdown";
+ WriteToPowerStateSocket(power_state_str);
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+ EXPECT_EQ(ReadFromPowerStateMarkerFile(), power_state_str);
+ }
+}
+
+} // namespace android::hardware::automotive::vehicle::V2_0::impl