diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2021-04-10 01:01:08 +0000 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2021-04-10 01:01:08 +0000 |
commit | ca6e3c731fc689c689a5c7ec0952a5a826e29f05 (patch) | |
tree | ebca1ed7bd934a7b6073b2777636df8729b85e1d | |
parent | f36af165a57540518041d7f8a8c9a73d557cf7aa (diff) | |
parent | b0f818e016c66f8fbef006aad07a3f4504d77704 (diff) | |
download | trout-android11-qpr3-s1-release.tar.gz |
Snap for 7272552 from b0f818e016c66f8fbef006aad07a3f4504d77704 to rvc-qpr3-releaseandroid-11.0.0_r46android-11.0.0_r43android-11.0.0_r40android-11.0.0_r39android-11.0.0_r38android11-qpr3-s1-releaseandroid11-qpr3-release
Change-Id: Ia6da2122244a09dca53cfe2b8e9ba93e2a4e626a
-rw-r--r-- | hal/audio/6.0/audio_hw.c | 83 | ||||
-rw-r--r-- | tests/hal/vehicle/2.0/Android.bp | 32 | ||||
-rw-r--r-- | tests/hal/vehicle/2.0/GrpcServer_test.cpp | 162 |
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 |