--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Seungbae Shin <seungbae.shin@samsung.com>
+ *
+ * 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 <string.h>
+#include <unistd.h>
+#include <iostream>
+#include <fstream>
+#include <array>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <gtest/gtest.h>
+#include <system_info.h>
+
+#include <hal-audio-interface.h>
+#include <hal-audio.h>
+
+#include "parser.hh"
+
+using namespace std;
+
+#define USE_IFSTREAM
+#define DISABLE_DEBUG_LOG
+
+typedef void *pcm_handle;
+
+typedef enum audio_sample_format {
+ AUDIO_SAMPLE_U8,
+ AUDIO_SAMPLE_ALAW,
+ AUDIO_SAMPLE_ULAW,
+ AUDIO_SAMPLE_S16LE,
+ AUDIO_SAMPLE_S16BE,
+ AUDIO_SAMPLE_FLOAT32LE,
+ AUDIO_SAMPLE_FLOAT32BE,
+ AUDIO_SAMPLE_S32LE,
+ AUDIO_SAMPLE_S32BE,
+ AUDIO_SAMPLE_S24LE,
+ AUDIO_SAMPLE_S24BE,
+ AUDIO_SAMPLE_S24_32LE,
+ AUDIO_SAMPLE_S24_32BE,
+ AUDIO_SAMPLE_MAX,
+ AUDIO_SAMPLE_INVALID = -1
+} audio_sample_format_t;
+
+typedef struct {
+ audio_sample_format_t format;
+ uint32_t rate;
+ uint8_t channels;
+} audio_pcm_sample_spec_t;
+
+/*
+ * TestSuite Class
+ */
+class AudioHalTest : public testing::Test
+{
+ public:
+ virtual void SetUp();
+ virtual void TearDown();
+
+ protected:
+ void SetRouteToSpeaker();
+ void SetRouteToMicrophone();
+ int32_t WritePcmFromFile(pcm_handle pcm_h);
+ int32_t ReadPcmFromDevice(pcm_handle pcm_h);
+ uint32_t BytesToFrames(uint32_t bytes, audio_pcm_sample_spec_t *spec);
+ uint32_t BytesToFrames(uint32_t bytes);
+ uint32_t FramesToBytes(uint32_t frames, audio_pcm_sample_spec_t *spec);
+ uint32_t FramesToBytes(uint32_t frames);
+ uint32_t GetDefaultFrames();
+
+ static void HalMessageCallback(const char *name, int value, void *user_data);
+
+ void *m_h;
+ audio_pcm_sample_spec_t m_spec;
+
+ // Todo : following value may vary depends on targets
+ const int default_frames = 6400;
+ const int default_periods = 5;
+ const int default_rate = 44100;
+ const int default_channels = 2;
+
+ // ToDo : following types may need to be fixed.
+ const array<string, 8> vol_types = { "system", "notification", "alarm", "ringtone",
+ "media", "call", "voip", "voice" };
+
+};
+
+void AudioHalTest::SetUp()
+{
+ m_h = nullptr;
+
+ int32_t ret = hal_audio_init(&m_h);
+ if (ret != AUDIO_RET_OK)
+ cout << "audio hal init failed : " << ret << endl;
+}
+
+void AudioHalTest::TearDown()
+{
+ if (m_h == nullptr)
+ return;
+
+ int32_t ret = hal_audio_deinit(m_h);
+ if (ret != AUDIO_RET_OK)
+ cout << "audio hal deinit failed : " << ret << endl;
+
+ m_h = nullptr;
+}
+
+void AudioHalTest::SetRouteToSpeaker()
+{
+ audio_route_info info;
+ int32_t num_of_devices = 1;
+
+ memset(&info, 0, sizeof(audio_route_info));
+
+ info.role = "media";
+ info.device_infos = (device_info_s*)malloc(sizeof(device_info_s) * num_of_devices);
+ if (info.device_infos == nullptr) {
+ cout << "malloc error!!! : " << errno << endl;
+ return;
+ }
+ info.device_infos[0].direction = AUDIO_DIRECTION_OUT;
+ info.device_infos[0].type = "builtin-speaker";
+ info.device_infos[0].id = 100;
+ info.num_of_devices = num_of_devices;
+
+ int32_t ret = hal_audio_update_route(m_h, &info);
+ cout << "update route : " << ret << endl;
+
+ free(info.device_infos);
+}
+
+void AudioHalTest::SetRouteToMicrophone()
+{
+ audio_route_info info;
+ int32_t num_of_devices = 1;
+
+ memset(&info, 0, sizeof(audio_route_info));
+
+ info.role = "media";
+ info.device_infos = (device_info_s*)malloc(sizeof(device_info_s) * num_of_devices);
+ if (info.device_infos == nullptr) {
+ cout << "malloc error!!! : " << errno << endl;
+ return;
+ }
+ info.device_infos[0].direction = AUDIO_DIRECTION_IN;
+ info.device_infos[0].type = "builtin-mic";
+ info.device_infos[0].id = 100;
+ info.num_of_devices = num_of_devices;
+
+ int32_t ret = hal_audio_update_route(m_h, &info);
+ cout << "update route : " << ret << endl;
+
+ free(info.device_infos);
+}
+
+int32_t AudioHalTest::WritePcmFromFile(pcm_handle pcm_h)
+{
+ int32_t ret = AUDIO_RET_OK;
+ uint32_t avail_frames = 0;
+ int bytes_read;
+ char buffer[65536];
+
+ const char res_path[] = "/usr/share/testcase/res/audio/test_16le_44100_2ch.raw";
+#ifdef USE_IFSTREAM
+ ifstream fs;
+ fs.open(res_path, fstream::in | fstream::binary);
+ if (fs.fail()) {
+ cout << "Failed to open : " << res_path << endl;
+ return AUDIO_ERR_INTERNAL;
+ }
+#else
+ int fd = open(res_path, O_RDONLY);
+ if (fd == -1) {
+ cout << "Failed to open : " << res_path << ", " << errno << endl;
+ return AUDIO_ERR_INTERNAL;
+ }
+#endif
+
+ cout << "start to play dtmf+noise sounds ( " << res_path << " ) for 5 sec. " << endl;
+
+ while (1) {
+ ret = hal_audio_pcm_avail(m_h, pcm_h, &avail_frames);
+ if (ret == AUDIO_ERR_INTERNAL)
+ break;
+
+ if (avail_frames == 0) {
+ usleep(20000); // 20ms
+ continue;
+ }
+
+#ifdef USE_IFSTREAM
+ fs.read(buffer, FramesToBytes(avail_frames));
+ bytes_read = fs.gcount();
+#else
+ bytes_read = read(fd, buffer, FramesToBytes(avail_frames));
+#endif
+
+ cout << "avail frames : " << avail_frames << ", read_n : " << bytes_read << endl;
+
+ ret = hal_audio_pcm_write(m_h, pcm_h, buffer, BytesToFrames(bytes_read));
+ if (ret == AUDIO_ERR_INTERNAL)
+ break;
+
+#ifdef USE_IFSTREAM
+ if (!fs.good()) {
+ if (fs.eof())
+ cout << "EOS!!!" << endl;
+ else if (fs.fail() || fs.bad())
+ cout << "Error..." << endl;
+ break;
+ }
+#else
+ if (bytes_read < static_cast<int>(FramesToBytes(avail_frames))) {
+ cout << "EOS!!!" << endl;
+ break;
+ }
+#endif
+ }
+
+#ifdef USE_IFSTREAM
+ fs.close();
+#else
+ close(fd);
+#endif
+
+ cout << "Done!!!" << endl;
+
+ return ret;
+}
+
+int32_t AudioHalTest::ReadPcmFromDevice(pcm_handle pcm_h)
+{
+ int32_t ret = AUDIO_RET_OK;
+ uint32_t avail_frames = 0;
+ char buffer[65536];
+ int iter_left = 100;
+
+ cout << "start to record for few seconds..." << endl;
+
+ do {
+ ret = hal_audio_pcm_avail(m_h, pcm_h, &avail_frames);
+ if (ret == AUDIO_ERR_INTERNAL)
+ break;
+
+ if (avail_frames == 0) {
+ usleep(20000); // 20ms
+ continue;
+ }
+
+ ret = hal_audio_pcm_read(m_h, pcm_h, buffer, avail_frames);
+ if (ret == AUDIO_ERR_INTERNAL)
+ break;
+
+ cout << iter_left << ", read success, avail frames : " << avail_frames << endl;
+ } while (--iter_left);
+
+ cout << "Done!!!" << endl;
+
+ return ret;
+}
+
+uint32_t AudioHalTest::BytesToFrames(uint32_t bytes, audio_pcm_sample_spec_t *spec)
+{
+ // ToDo : support various sample format
+ return (spec->format == AUDIO_SAMPLE_S16LE) ? bytes / spec->channels / 2 : 0;
+}
+
+uint32_t AudioHalTest::BytesToFrames(uint32_t bytes)
+{
+ // ToDo : support various sample format
+ return (m_spec.format == AUDIO_SAMPLE_S16LE) ? bytes / m_spec.channels / 2 : 0;
+}
+
+uint32_t AudioHalTest::FramesToBytes(uint32_t frames, audio_pcm_sample_spec_t *spec)
+{
+ // ToDo : support various sample format
+ return (spec->format == AUDIO_SAMPLE_S16LE) ? frames * spec->channels * 2 : 0;
+}
+
+uint32_t AudioHalTest::FramesToBytes(uint32_t frames)
+{
+ // ToDo : support various sample format
+ return (m_spec.format == AUDIO_SAMPLE_S16LE) ? frames * m_spec.channels * 2 : 0;
+}
+
+uint32_t AudioHalTest::GetDefaultFrames()
+{
+ return BytesToFrames(default_frames);
+}
+
+void AudioHalTest::HalMessageCallback(const char *name, int value, void *user_data)
+{
+ cout << name << "," << value << "," << user_data << endl;
+}
+
+/**
+ * @testcase InitP
+ * @since_tizen 4.0
+ * @author SR(seungbae.shin)
+ * @reviewer SR(sc11.lee)
+ * @type auto
+ * @description Positive, Initialize audio HAL handle
+ * @apicovered audio_init, audio_deinit
+ * @passcase XXX
+ * @failcase YYY
+ * @precondition None
+ * @postcondition None
+ */
+TEST(AudioHalPreTest, InitP)
+{
+ void *h = nullptr;
+
+ int32_t ret = hal_audio_init(&h);
+ ASSERT_EQ(ret, AUDIO_RET_OK);
+ ASSERT_NE(h, nullptr);
+
+ ret = hal_audio_deinit(h);
+ EXPECT_EQ(ret, AUDIO_RET_OK);
+}
+
+/**
+ * @testcase InitN
+ * @since_tizen 4.0
+ * @author SR(seungbae.shin)
+ * @reviewer SR(sc11.lee)
+ * @type auto
+ * @description Negative, Initialize audio HAL handle
+ * @apicovered audio_init
+ * @passcase XXX
+ * @failcase YYY
+ * @precondition None
+ * @postcondition None
+ */
+TEST(AudioHalPreTest, InitN)
+{
+ int32_t ret = hal_audio_init(nullptr);
+ ASSERT_EQ(ret, AUDIO_ERR_PARAMETER);
+}
+
+/**
+ * @testcase DeinitP
+ * @since_tizen 4.0
+ * @author SR(seungbae.shin)
+ * @reviewer SR(sc11.lee)
+ * @type auto
+ * @description Positive, Deinitialize audio HAL handle
+ * @apicovered audio_init, audio_deinit
+ * @passcase XXX
+ * @failcase YYY
+ * @precondition None
+ * @postcondition None
+ */
+TEST(AudioHalPreTest, DeinitP)
+{
+ void *h = nullptr;
+
+ int32_t ret = hal_audio_init(&h);
+ ASSERT_EQ(ret, AUDIO_RET_OK);
+ ASSERT_NE(h, nullptr);
+
+ ret = hal_audio_deinit(h);
+ ASSERT_EQ(ret, AUDIO_RET_OK);
+}
+
+/**
+ * @testcase GetVolumeLevelMaxP
+ * @since_tizen 4.0
+ * @author SR(seungbae.shin)
+ * @reviewer SR(sc11.lee)
+ * @type auto
+ * @description Positive, Get maximum volume level of each volume types
+ * @apicovered audio_get_volume_level_max
+ * @passcase XXX
+ * @failcase YYY
+ * @precondition None
+ * @postcondition None
+ */
+TEST_F(AudioHalTest, GetVolumeLevelMaxP)
+{
+ uint32_t level_max;
+ audio_volume_info_s info = { NULL, NULL, AUDIO_DIRECTION_OUT };
+
+ for (const auto& i : vol_types) {
+ info.type = i.c_str();
+ int32_t ret = hal_audio_get_volume_level_max(m_h, &info, &level_max);
+ cout << i << " : " << level_max << endl;
+ EXPECT_EQ(ret, AUDIO_RET_OK);
+ }
+}
+
+/**
+ * @testcase GetVolumeLevelMaxN
+ * @since_tizen 4.0
+ * @author SR(seungbae.shin)
+ * @reviewer SR(sc11.lee)
+ * @type auto
+ * @description Negative, Get maximum volume level of each volume types
+ * @apicovered audio_get_volume_level_max
+ * @passcase XXX
+ * @failcase YYY
+ * @precondition None
+ * @postcondition None
+ */
+TEST_F(AudioHalTest, GetVolumeLevelMaxN)
+{
+ audio_volume_info_s info = { "media", NULL, AUDIO_DIRECTION_OUT };
+ int32_t ret = hal_audio_get_volume_level_max(m_h, &info, nullptr);
+ EXPECT_EQ(ret, AUDIO_ERR_PARAMETER);
+}
+
+/**
+ * @testcase GetVolumeLevelP
+ * @since_tizen 4.0
+ * @author SR(seungbae.shin)
+ * @reviewer SR(sc11.lee)
+ * @type auto
+ * @description Positive, Get volume level of each volume types
+ * @apicovered audio_get_volume_level
+ * @passcase XXX
+ * @failcase YYY
+ * @precondition None
+ * @postcondition None
+ */
+TEST_F(AudioHalTest, GetVolumeLevelP)
+{
+ uint32_t level;
+ int32_t ret;
+ audio_volume_info_s info = { NULL, NULL, AUDIO_DIRECTION_OUT };
+
+ for (const auto& i : vol_types) {
+ info.type = i.c_str();
+ ret = hal_audio_get_volume_level(m_h, &info, &level);
+ cout << i << " : " << level << endl;
+ EXPECT_EQ(ret, AUDIO_RET_OK);
+ }
+}
+
+/**
+ * @testcase GetVolumeLevelN
+ * @since_tizen 4.0
+ * @author SR(seungbae.shin)
+ * @reviewer SR(sc11.lee)
+ * @type auto
+ * @description Negative, Get volume level of each volume types
+ * @apicovered audio_get_volume_level
+ * @passcase XXX
+ * @failcase YYY
+ * @precondition None
+ * @postcondition None
+ */
+TEST_F(AudioHalTest, GetVolumeLevelN)
+{
+ audio_volume_info_s info = { "media", NULL, AUDIO_DIRECTION_OUT };
+ int32_t ret = hal_audio_get_volume_level(m_h, &info, nullptr);
+ EXPECT_EQ(ret, AUDIO_ERR_PARAMETER);
+}
+
+/**
+ * @testcase SetVolumeLevelP
+ * @since_tizen 4.0
+ * @author SR(seungbae.shin)
+ * @reviewer SR(sc11.lee)
+ * @type auto
+ * @description Positive, Set volume level of each volume types
+ * @apicovered audio_set_volume_level
+ * @passcase XXX
+ * @failcase YYY
+ * @precondition None
+ * @postcondition None
+ */
+TEST_F(AudioHalTest, SetVolumeLevelP)
+{
+ /* FIXME : need to revise */
+ audio_volume_info_s info = { "media", NULL, AUDIO_DIRECTION_OUT };
+ int32_t ret = hal_audio_set_volume_level(m_h, &info, 15);
+ EXPECT_EQ(ret, AUDIO_RET_OK);
+
+ ret = hal_audio_set_volume_level(m_h, &info, 7);
+ EXPECT_EQ(ret, AUDIO_RET_OK);
+}
+
+
+/**
+ * @testcase SetVolumeLevelN
+ * @since_tizen 4.0
+ * @author SR(seungbae.shin)
+ * @reviewer SR(sc11.lee)
+ * @type auto
+ * @description Negative, Set volume level of each volume types
+ * @apicovered audio_set_volume_level
+ * @passcase XXX
+ * @failcase YYY
+ * @precondition None
+ * @postcondition None
+ */
+TEST_F(AudioHalTest, SetVolumeLevelN)
+{
+ audio_volume_info_s info = { "media", NULL, AUDIO_DIRECTION_OUT };
+ int32_t ret = hal_audio_set_volume_level(m_h, &info, 10000);
+ EXPECT_EQ(ret, AUDIO_ERR_PARAMETER);
+}
+
+
+/**
+ * @testcase GetVolumeValueP
+ * @since_tizen 4.0
+ * @author SR(seungbae.shin)
+ * @reviewer SR(sc11.lee)
+ * @type auto
+ * @description Positive, Get volume value of each volume types with given volume level
+ * @apicovered audio_get_volume_value
+ * @passcase XXX
+ * @failcase YYY
+ * @precondition None
+ * @postcondition None
+ */
+TEST_F(AudioHalTest, GetVolumeValueP)
+{
+ double value;
+ uint32_t level_max;
+ int32_t ret;
+ audio_volume_info_s info = { NULL, NULL, AUDIO_DIRECTION_OUT };
+
+ for (const auto& i : vol_types) {
+ info.type = i.c_str();
+ ret = hal_audio_get_volume_level_max(m_h, &info, &level_max);
+ EXPECT_EQ(ret, AUDIO_RET_OK);
+
+ for (uint32_t l = 0; l < level_max ; l++) {
+ info.type = i.c_str();
+ ret = hal_audio_get_volume_value(m_h, &info, l, &value);
+ EXPECT_EQ(ret, AUDIO_RET_OK);
+ cout << i << ", level " << l << ", value : " << value << endl;
+ }
+ }
+}
+
+/**
+ * @testcase GetVolumeValueN
+ * @since_tizen 4.0
+ * @author SR(seungbae.shin)
+ * @reviewer SR(sc11.lee)
+ * @type auto
+ * @description Negative, Get volume value of each volume types with given volume level
+ * @apicovered audio_get_volume_value
+ * @passcase XXX
+ * @failcase YYY
+ * @precondition None
+ * @postcondition None
+ */
+TEST_F(AudioHalTest, GetVolumeValueN)
+{
+ audio_volume_info_s info = { "media", NULL, AUDIO_DIRECTION_OUT };
+ int32_t ret = hal_audio_get_volume_value(m_h, &info, 0, nullptr);
+ EXPECT_EQ(ret, AUDIO_ERR_PARAMETER);
+}
+
+/**
+ * @testcase GetVolumeMuteP
+ * @since_tizen 4.0
+ * @author SR(seungbae.shin)
+ * @reviewer SR(sc11.lee)
+ * @type auto
+ * @description Positive, Get volume mute of each volume types.
+ * @apicovered audio_get_volume_mute
+ * @passcase XXX
+ * @failcase YYY
+ * @precondition None
+ * @postcondition None
+ */
+TEST_F(AudioHalTest, GetVolumeMuteP)
+{
+ uint32_t mute = 0;
+ int32_t ret;
+ audio_volume_info_s info = { NULL, NULL, AUDIO_DIRECTION_OUT };
+
+ for (const auto& i : vol_types) {
+ info.type = i.c_str();
+ ret = hal_audio_get_volume_mute(m_h, &info, &mute);
+ EXPECT_EQ(ret, AUDIO_RET_OK);
+ cout << i << " mute : " << mute << endl;
+ }
+}
+
+/**
+ * @testcase GetVolumeMuteN
+ * @since_tizen 4.0
+ * @author SR(seungbae.shin)
+ * @reviewer SR(sc11.lee)
+ * @type auto
+ * @description Negative, Get volume mute of each volume types.
+ * @apicovered audio_get_volume_mute
+ * @passcase XXX
+ * @failcase YYY
+ * @precondition None
+ * @postcondition None
+ */
+TEST_F(AudioHalTest, GetVolumeMuteN)
+{
+ audio_volume_info_s info = { "media", NULL, AUDIO_DIRECTION_OUT };
+ int32_t ret = hal_audio_get_volume_mute(m_h, &info, nullptr);
+ EXPECT_EQ(ret, AUDIO_ERR_PARAMETER);
+}
+
+/**
+ * @testcase SetVolumeMuteP
+ * @since_tizen 4.0
+ * @author SR(seungbae.shin)
+ * @reviewer SR(sc11.lee)
+ * @type auto
+ * @description Positive, Set volume mute of each volume types.
+ * @apicovered audio_set_volume_mute
+ * @passcase XXX
+ * @failcase YYY
+ * @precondition None
+ * @postcondition None
+ */
+TEST_F(AudioHalTest, SetVolumeMuteP)
+{
+ audio_volume_info_s info = { "media", NULL, AUDIO_DIRECTION_OUT };
+ int32_t ret = hal_audio_set_volume_mute(m_h, &info, 1);
+ EXPECT_EQ(ret, AUDIO_RET_OK);
+
+ ret = hal_audio_set_volume_mute(m_h, &info, 0);
+ EXPECT_EQ(ret, AUDIO_RET_OK);
+}
+
+#if 0 // can't test because mute is not implemented yet...
+TEST_F(AudioHalTest, SetVolumeMuteN)
+{
+ int32_t ret = hal_audio_set_volume_mute(m_h, "media", AUDIO_DIRECTION_OUT, 10000);
+ EXPECT_EQ(ret, AUDIO_ERR_INTERNAL);
+}
+#endif
+
+/**
+ * @testcase UpdateRouteP
+ * @since_tizen 4.0
+ * @author SR(seungbae.shin)
+ * @reviewer SR(sc11.lee)
+ * @type auto
+ * @description Positive, Update route
+ * @apicovered audio_update_route
+ * @passcase XXX
+ * @failcase YYY
+ * @precondition None
+ * @postcondition None
+ */
+TEST_F(AudioHalTest, UpdateRouteP)
+{
+ audio_route_info info;
+ int32_t num_of_devices = 1;
+
+ memset(&info, 0, sizeof(audio_route_info));
+
+ info.role = "media";
+ info.device_infos = (device_info_s*)malloc(sizeof(device_info_s) * num_of_devices);
+ ASSERT_NE(info.device_infos, nullptr);
+ info.device_infos[0].direction = AUDIO_DIRECTION_OUT;
+ info.device_infos[0].type = "builtin-speaker";
+ info.device_infos[0].id = 100;
+ info.num_of_devices = num_of_devices;
+
+ int32_t ret = hal_audio_update_route(m_h, &info);
+ EXPECT_EQ(ret, AUDIO_RET_OK);
+
+ free(info.device_infos);
+}
+
+
+/**
+ * @testcase UpdateRouteN
+ * @since_tizen 4.0
+ * @author SR(seungbae.shin)
+ * @reviewer SR(sc11.lee)
+ * @type auto
+ * @description Negative, Update route
+ * @apicovered audio_update_route
+ * @passcase XXX
+ * @failcase YYY
+ * @precondition None
+ * @postcondition None
+ */
+TEST_F(AudioHalTest, UpdateRouteN)
+{
+ int32_t ret = hal_audio_update_route(m_h, nullptr);
+ EXPECT_EQ(ret, AUDIO_ERR_PARAMETER);
+
+ audio_route_info info;
+ memset(&info, 0, sizeof(audio_route_info));
+ info.role = nullptr;
+ ret = hal_audio_update_route(m_h, &info);
+ EXPECT_EQ(ret, AUDIO_ERR_PARAMETER);
+}
+
+/**
+ * @testcase UpdateRouteOptionP
+ * @since_tizen 4.0
+ * @author SR(seungbae.shin)
+ * @reviewer SR(sc11.lee)
+ * @type auto
+ * @description Positive, Update route option
+ * @apicovered audio_update_route_option
+ * @passcase XXX
+ * @failcase YYY
+ * @precondition None
+ * @postcondition None
+ */
+TEST_F(AudioHalTest, UpdateRouteOptionP)
+{
+ audio_route_option_s option;
+
+ int32_t ret = hal_audio_update_route_option(m_h, &option);
+ EXPECT_EQ(ret, AUDIO_RET_OK);
+}
+
+
+/**
+ * @testcase UpdateRouteOptionN
+ * @since_tizen 4.0
+ * @author SR(seungbae.shin)
+ * @reviewer SR(sc11.lee)
+ * @type auto
+ * @description Negative, Update route option
+ * @apicovered audio_update_route_option
+ * @passcase XXX
+ * @failcase YYY
+ * @precondition None
+ * @postcondition None
+ */
+TEST_F(AudioHalTest, UpdateRouteOptionN)
+{
+ int32_t ret = hal_audio_update_route_option(m_h, nullptr);
+ EXPECT_EQ(ret, AUDIO_ERR_PARAMETER);
+}
+
+/**
+ * @testcase NotifyStreamConnectionChangedP
+ * @since_tizen 4.0
+ * @author SR(seungbae.shin)
+ * @reviewer SR(sc11.lee)
+ * @type auto
+ * @description Positive, Notify stream connection changed
+ * @apicovered audio_notify_stream_connection_changed
+ * @passcase XXX
+ * @failcase YYY
+ * @precondition None
+ * @postcondition None
+ */
+TEST_F(AudioHalTest, NotifyStreamConnectionChangedP)
+{
+ audio_stream_info_s info;
+
+ memset(&info, 0, sizeof(audio_stream_info_s));
+ info.role = "media";
+ info.direction = AUDIO_DIRECTION_OUT;
+ info.idx = 100;
+
+ int32_t ret = hal_audio_notify_stream_connection_changed(m_h, &info, 1);
+ EXPECT_EQ(ret, AUDIO_RET_OK);
+}
+
+/**
+ * @testcase NotifyStreamConnectionChangedN
+ * @since_tizen 4.0
+ * @author SR(seungbae.shin)
+ * @reviewer SR(sc11.lee)
+ * @type auto
+ * @description Negative, Notify stream connection changed
+ * @apicovered audio_notify_stream_connection_changed
+ * @passcase XXX
+ * @failcase YYY
+ * @precondition None
+ * @postcondition None
+ */
+TEST_F(AudioHalTest, NotifyStreamConnectionChangedN)
+{
+ // check for nullptr ptr
+ int32_t ret = hal_audio_notify_stream_connection_changed(m_h, nullptr, 1);
+ EXPECT_EQ(ret, AUDIO_ERR_PARAMETER);
+
+ // check for invalid role
+ audio_stream_info_s info;
+ memset(&info, 0, sizeof(audio_stream_info_s));
+ info.role = nullptr;
+ info.direction = AUDIO_DIRECTION_OUT;
+ info.idx = 100;
+
+ ret = hal_audio_notify_stream_connection_changed(m_h, &info, 1);
+ EXPECT_EQ(ret, AUDIO_ERR_PARAMETER);
+}
+
+/**
+ * @testcase MessageCallbackP
+ * @since_tizen 4.0
+ * @author SR(seungbae.shin)
+ * @reviewer SR(sc11.lee)
+ * @type auto
+ * @description Positive, add/remove message callback
+ * @apicovered audio_add_message_cb, audio_remove_message_cb
+ * @passcase XXX
+ * @failcase YYY
+ * @precondition None
+ * @postcondition None
+ */
+TEST_F(AudioHalTest, MessageCallbackP)
+{
+ int32_t ret = hal_audio_add_message_cb(m_h, HalMessageCallback, nullptr);
+ ASSERT_EQ(ret, AUDIO_RET_OK);
+
+ ret = hal_audio_remove_message_cb(m_h, HalMessageCallback);
+ EXPECT_EQ(ret, AUDIO_RET_OK);
+}
+
+/**
+ * @testcase MessageCallbackN
+ * @since_tizen 4.0
+ * @author SR(seungbae.shin)
+ * @reviewer SR(sc11.lee)
+ * @type auto
+ * @description Negative, add/remove message callback
+ * @apicovered audio_add_message_cb, audio_remove_message_cb
+ * @passcase XXX
+ * @failcase YYY
+ * @precondition None
+ * @postcondition None
+ */
+TEST_F(AudioHalTest, MessageCallbackN)
+{
+ int32_t ret = hal_audio_add_message_cb(m_h, nullptr, nullptr);
+ ASSERT_EQ(ret, AUDIO_ERR_PARAMETER);
+
+ ret = hal_audio_remove_message_cb(m_h, nullptr);
+ EXPECT_EQ(ret, AUDIO_ERR_PARAMETER);
+}
+
+
+/**
+ * @testcase PcmGetFdP
+ * @since_tizen 4.0
+ * @author SR(seungbae.shin)
+ * @reviewer SR(sc11.lee)
+ * @type auto
+ * @description Positive, get fd from the pcm handle
+ * @apicovered audio_pcm_get_fd, audio_pcm_open, audio_pcm_close
+ * @passcase XXX
+ * @failcase YYY
+ * @precondition None
+ * @postcondition None
+ */
+TEST_F(AudioHalTest, PcmGetFdP)
+{
+ pcm_handle pcm_h = nullptr;
+
+ string card, dev;
+ int rate = default_rate, channels = default_channels;
+
+ CDeviceMapParser parser;
+ parser.get_playback(card, dev, rate, channels);
+
+ m_spec.format = AUDIO_SAMPLE_S16LE;
+ m_spec.rate = rate;
+ m_spec.channels = channels;
+
+ SetRouteToSpeaker();
+
+ int32_t ret = hal_audio_pcm_open(m_h, card.c_str(), dev.c_str(),
+ AUDIO_DIRECTION_OUT, &m_spec,
+ GetDefaultFrames(), default_periods, &pcm_h);
+ ASSERT_EQ(ret, AUDIO_RET_OK);
+
+ int pcm_fd = -1;
+ ret = hal_audio_pcm_get_fd(m_h, pcm_h, &pcm_fd);
+ EXPECT_EQ(ret, AUDIO_RET_OK);
+ cout << "pcm fd : " << pcm_fd << endl;
+
+ ret = hal_audio_pcm_close(m_h, pcm_h);
+ EXPECT_EQ(ret, AUDIO_RET_OK);
+}
+
+/**
+ * @testcase PcmGetFdN
+ * @since_tizen 4.0
+ * @author SR(seungbae.shin)
+ * @reviewer SR(sc11.lee)
+ * @type auto
+ * @description Negative, get fd from the pcm handle
+ * @apicovered audio_pcm_get_fd, audio_pcm_open, audio_pcm_close
+ * @passcase XXX
+ * @failcase YYY
+ * @precondition None
+ * @postcondition None
+ */
+TEST_F(AudioHalTest, PcmGetFdN)
+{
+ // check for pcm handle
+ int pcm_fd = -1;
+ int32_t ret = hal_audio_pcm_get_fd(m_h, nullptr, &pcm_fd);
+ EXPECT_EQ(ret, AUDIO_ERR_PARAMETER);
+
+ // check for fd
+ pcm_handle pcm_h = nullptr;
+ string card, dev;
+ int rate = default_rate, channels = default_channels;
+
+ CDeviceMapParser parser;
+ parser.get_playback(card, dev, rate, channels);
+
+ m_spec.format = AUDIO_SAMPLE_S16LE;
+ m_spec.rate = rate;
+ m_spec.channels = channels;
+
+ SetRouteToSpeaker();
+
+ ret = hal_audio_pcm_open(m_h, card.c_str(), dev.c_str(),
+ AUDIO_DIRECTION_OUT, &m_spec,
+ GetDefaultFrames(), default_periods, &pcm_h);
+ ASSERT_EQ(ret, AUDIO_RET_OK);
+
+ ret = hal_audio_pcm_get_fd(m_h, pcm_h, nullptr);
+ EXPECT_EQ(ret, AUDIO_ERR_PARAMETER);
+
+ ret = hal_audio_pcm_close(m_h, pcm_h);
+ EXPECT_EQ(ret, AUDIO_RET_OK);
+}
+
+/**
+ * @testcase PcmOpenWriteCloseP
+ * @since_tizen 4.0
+ * @author SR(seungbae.shin)
+ * @reviewer SR(sc11.lee)
+ * @type auto
+ * @description Positive, open pcm handle, start pcm handle, write pcm buffers, stop pcm handle and close pcm_handle
+ * @apicovered audio_pcm_open, audio_pcm_start, audio_pcm_avail, audio_pcm_write, audio_pcm_stop, audio_pcm_close
+ * @passcase XXX
+ * @failcase YYY
+ * @precondition None
+ * @postcondition None
+ */
+TEST_F(AudioHalTest, PcmOpenWriteCloseP)
+{
+ pcm_handle pcm_h = nullptr;
+ string card, dev;
+ int rate = default_rate, channels = default_channels;
+
+ CDeviceMapParser parser;
+ parser.get_playback(card, dev, rate, channels);
+
+ m_spec.format = AUDIO_SAMPLE_S16LE;
+ m_spec.rate = rate;
+ m_spec.channels = channels;
+
+ SetRouteToSpeaker();
+
+ int32_t ret = hal_audio_pcm_open(m_h, card.c_str(), dev.c_str(),
+ AUDIO_DIRECTION_OUT, &m_spec,
+ GetDefaultFrames(), default_periods, &pcm_h);
+ ASSERT_EQ(ret, AUDIO_RET_OK);
+
+ ret = hal_audio_pcm_start(m_h, pcm_h);
+ EXPECT_EQ(ret, AUDIO_RET_OK);
+
+ ret = WritePcmFromFile(pcm_h);
+ EXPECT_EQ(ret, AUDIO_RET_OK);
+
+ ret = hal_audio_pcm_stop(m_h, pcm_h);
+ EXPECT_EQ(ret, AUDIO_RET_OK);
+
+ ret = hal_audio_pcm_close(m_h, pcm_h);
+ EXPECT_EQ(ret, AUDIO_RET_OK);
+}
+
+/**
+ * @testcase PcmOpenReadCloseP
+ * @since_tizen 4.0
+ * @author SR(seungbae.shin)
+ * @reviewer SR(sc11.lee)
+ * @type auto
+ * @description Positive, open pcm handle, start pcm handle, read pcm buffers, stop pcm handle and close pcm_handle
+ * @apicovered audio_pcm_open, audio_pcm_start, audio_pcm_avail, audio_pcm_read, audio_pcm_stop, audio_pcm_close
+ * @passcase XXX
+ * @failcase YYY
+ * @precondition None
+ * @postcondition None
+ */
+TEST_F(AudioHalTest, PcmOpenReadCloseP)
+{
+ pcm_handle pcm_h = nullptr;
+ string card, dev;
+ int rate = default_rate, channels = default_channels;
+
+ CDeviceMapParser parser;
+ parser.get_capture(card, dev, rate, channels);
+
+ m_spec.format = AUDIO_SAMPLE_S16LE;
+ m_spec.rate = rate;
+ m_spec.channels = channels;
+
+ SetRouteToMicrophone();
+
+ int32_t ret = hal_audio_pcm_open(m_h, card.c_str(), dev.c_str(),
+ AUDIO_DIRECTION_IN, &m_spec,
+ GetDefaultFrames(), default_periods, &pcm_h);
+ ASSERT_EQ(ret, AUDIO_RET_OK);
+
+ ret = hal_audio_pcm_start(m_h, pcm_h);
+ EXPECT_EQ(ret, AUDIO_RET_OK);
+
+ ret = ReadPcmFromDevice(pcm_h);
+ EXPECT_EQ(ret, AUDIO_RET_OK);
+
+ ret = hal_audio_pcm_stop(m_h, pcm_h);
+ EXPECT_EQ(ret, AUDIO_RET_OK);
+
+ ret = hal_audio_pcm_close(m_h, pcm_h);
+ EXPECT_EQ(ret, AUDIO_RET_OK);
+}
+
+/**
+ * @testcase PcmRecoverN
+ * @since_tizen 4.0
+ * @author SR(seungbae.shin)
+ * @reviewer SR(sc11.lee)
+ * @type auto
+ * @description Negative, pcm recovery
+ * @apicovered audio_pcm_recover
+ * @passcase XXX
+ * @failcase YYY
+ * @precondition None
+ * @postcondition None
+ */
+TEST_F(AudioHalTest, PcmRecoverN)
+{
+ int32_t ret = hal_audio_pcm_recover(m_h, nullptr, 0);
+ EXPECT_EQ(ret, AUDIO_ERR_PARAMETER);
+}
+
+/**
+ * @testcase PcmSetParamP
+ * @since_tizen 4.0
+ * @author SR(seungbae.shin)
+ * @reviewer SR(sc11.lee)
+ * @type auto
+ * @description Positive, set audio parameters
+ * @apicovered audio_pcm_pcm_set_param, audio_pcm_open, audio_pcm_close
+ * @passcase XXX
+ * @failcase YYY
+ * @precondition None
+ * @postcondition None
+ */
+TEST_F(AudioHalTest, PcmSetParamP)
+{
+ pcm_handle pcm_h = nullptr;
+ string card, dev;
+ int rate = default_rate, channels = default_channels;
+
+ CDeviceMapParser parser;
+ parser.get_playback(card, dev, rate, channels);
+
+ m_spec.format = AUDIO_SAMPLE_S16LE;
+ m_spec.rate = rate;
+ m_spec.channels = channels;
+
+ SetRouteToSpeaker();
+
+ int32_t ret = hal_audio_pcm_open(m_h, card.c_str(), dev.c_str(),
+ AUDIO_DIRECTION_OUT, &m_spec,
+ GetDefaultFrames(), default_periods, &pcm_h);
+ ASSERT_EQ(ret, AUDIO_RET_OK);
+
+ ret = hal_audio_pcm_set_params(m_h, pcm_h, AUDIO_DIRECTION_OUT, &m_spec,
+ GetDefaultFrames(), default_periods);
+ EXPECT_EQ(ret, AUDIO_RET_OK);
+
+ ret = hal_audio_pcm_close(m_h, pcm_h);
+ EXPECT_EQ(ret, AUDIO_RET_OK);
+}
+
+/**
+ * @testcase PcmSetParamN
+ * @since_tizen 4.0
+ * @author SR(seungbae.shin)
+ * @reviewer SR(sc11.lee)
+ * @type auto
+ * @description Negative, set audio parameters
+ * @apicovered audio_pcm_pcm_set_param, audio_pcm_open, audio_pcm_close
+ * @passcase XXX
+ * @failcase YYY
+ * @precondition None
+ * @postcondition None
+ */
+TEST_F(AudioHalTest, PcmSetParamN)
+{
+ pcm_handle pcm_h = nullptr;
+ string card, dev;
+ int rate = default_rate, channels = default_channels;
+
+ CDeviceMapParser parser;
+ parser.get_playback(card, dev, rate, channels);
+
+ m_spec.format = AUDIO_SAMPLE_S16LE;
+ m_spec.rate = rate;
+ m_spec.channels = channels;
+
+ SetRouteToSpeaker();
+
+ int32_t ret = hal_audio_pcm_open(m_h, card.c_str(), dev.c_str(),
+ AUDIO_DIRECTION_OUT, &m_spec, GetDefaultFrames(), default_periods, &pcm_h);
+ ASSERT_EQ(ret, AUDIO_RET_OK);
+
+ ret = hal_audio_pcm_set_params(m_h, nullptr, AUDIO_DIRECTION_OUT, &m_spec, GetDefaultFrames(), default_periods);
+ EXPECT_EQ(ret, AUDIO_ERR_PARAMETER);
+
+ ret = hal_audio_pcm_close(m_h, pcm_h);
+ EXPECT_EQ(ret, AUDIO_RET_OK);
+}
+
+/**
+ * @testcase PcmGetParamP
+ * @since_tizen 4.0
+ * @author SR(seungbae.shin)
+ * @reviewer SR(sc11.lee)
+ * @type auto
+ * @description Positive, get audio parameters
+ * @apicovered audio_pcm_pcm_get_param, audio_pcm_open, audio_pcm_close
+ * @passcase XXX
+ * @failcase YYY
+ * @precondition None
+ * @postcondition None
+ */
+TEST_F(AudioHalTest, PcmGetParamP)
+{
+ pcm_handle pcm_h = nullptr;
+ string card, dev;
+ int rate = default_rate, channels = default_channels;
+
+ CDeviceMapParser parser;
+ parser.get_playback(card, dev, rate, channels);
+
+ m_spec.format = AUDIO_SAMPLE_S16LE;
+ m_spec.rate = rate;
+ m_spec.channels = channels;
+
+ // Precondition
+ SetRouteToSpeaker();
+ int32_t ret = hal_audio_pcm_open(m_h, card.c_str(), dev.c_str(),
+ AUDIO_DIRECTION_OUT, &m_spec,
+ GetDefaultFrames(), default_periods, &pcm_h);
+ ASSERT_EQ(ret, AUDIO_RET_OK);
+
+ // Test Body
+ audio_pcm_sample_spec_t local_spec;
+ audio_pcm_sample_spec_t * p_spec = &local_spec;
+ uint32_t period_size = 0;
+ uint32_t periods = 0;
+
+ memset(p_spec, 0, sizeof(audio_pcm_sample_spec_t));
+ ret = hal_audio_pcm_get_params(m_h, pcm_h, AUDIO_DIRECTION_OUT, (void**)&p_spec, &period_size, &periods);
+ EXPECT_EQ(ret, AUDIO_RET_OK);
+
+ cout << p_spec->format << "," <<
+ p_spec->rate << "," <<
+ static_cast<int>(p_spec->channels) << "," <<
+ period_size << "," <<
+ periods << endl;
+
+ // Cleanup
+ ret = hal_audio_pcm_close(m_h, pcm_h);
+ EXPECT_EQ(ret, AUDIO_RET_OK);
+}
+
+/**
+ * @testcase PcmGetParamN
+ * @since_tizen 4.0
+ * @author SR(seungbae.shin)
+ * @reviewer SR(sc11.lee)
+ * @type auto
+ * @description Negative, get audio parameters
+ * @apicovered audio_pcm_pcm_get_param
+ * @passcase XXX
+ * @failcase YYY
+ * @precondition None
+ * @postcondition None
+ */
+TEST_F(AudioHalTest, PcmGetParamN)
+{
+ int32_t ret = hal_audio_pcm_get_params(m_h, nullptr, AUDIO_DIRECTION_OUT, nullptr, nullptr, nullptr);
+ EXPECT_EQ(ret, AUDIO_ERR_PARAMETER);
+}
+
+int main(int argc, char **argv)
+{
+#ifdef DISABLE_DEBUG_LOG
+ cout.rdbuf(NULL);
+#endif
+
+ testing::InitGoogleTest(&argc, argv);
+
+ return RUN_ALL_TESTS();
+}
--- /dev/null
+#include <iostream>
+#include <json.h>
+#include <assert.h>
+#include <string.h>
+#include <string>
+
+#include "parser.hh"
+
+#define DEVICE_FILE_OBJECT "device-files"
+#define DEVICE_TYPE_PROP_PLAYBACK_DEVICES "playback-devices"
+#define DEVICE_TYPE_PROP_CAPTURE_DEVICES "capture-devices"
+#define DEVICE_TYPE_PROP_DEVICE_STRING "device-string"
+#define DEVICE_TYPE_PROP_ROLE "role"
+
+/* device-files example
+ device-files : {
+ playback-devices : [
+ {
+ device-string : alsa:sprdphone,0,
+ role : { normal : rate=44100 }
+ }
+ {
+ device-string : alsa:VIRTUALAUDIOW,0,
+ role : { call-voice : rate=16000 channels=1 tsched=0 alternate_rate=16000 }
+ }
+ ]
+ capture-devices : [
+ {
+ device-string : alsa:sprdphone,0,
+ role : { normal : rate=44100 }
+ }
+ ]
+ }
+*/
+
+using namespace std;
+
+CDeviceMapParser::CDeviceMapParser()
+ : m_json_obj(nullptr), m_json_device_files_obj(nullptr)
+{
+ open_json("/etc/pulse/device-map.json");
+}
+
+CDeviceMapParser::CDeviceMapParser(const char* map_file)
+ : m_json_obj(nullptr), m_json_device_files_obj(nullptr)
+{
+ open_json(map_file);
+}
+
+CDeviceMapParser::~CDeviceMapParser()
+{
+ close_json();
+}
+
+void CDeviceMapParser::open_json(const char* json_file)
+{
+ m_json_obj = json_object_from_file(json_file);
+ if (!m_json_obj) {
+ cout << "Read device-map " << json_file << " failed" << endl;
+ return;
+ }
+
+ if (!json_object_object_get_ex(m_json_obj, DEVICE_FILE_OBJECT, &m_json_device_files_obj)) {
+ cout << "Get device files object failed" << endl;
+ return;
+ }
+ if (!json_object_is_type(m_json_device_files_obj, json_type_object)) {
+ cout << "json object type failed" << endl;
+ json_object_put(m_json_obj);
+ m_json_obj = nullptr;
+ return;
+ }
+
+ cout << DEVICE_FILE_OBJECT << " : {" << endl;
+}
+
+void CDeviceMapParser::close_json()
+{
+ if (!m_json_obj)
+ return;
+
+ json_object_put(m_json_obj);
+
+ cout << "}" << endl;
+}
+
+void CDeviceMapParser::parse_playback()
+{
+ json_object *playback_devices_o = nullptr;
+
+ if (!json_object_object_get_ex(m_json_device_files_obj, DEVICE_TYPE_PROP_PLAYBACK_DEVICES, &playback_devices_o)) {
+ cout << "failed to get playback" << endl;
+ return;
+ }
+
+ cout << " " << DEVICE_TYPE_PROP_PLAYBACK_DEVICES << " : [" << endl;
+ parse_device_file_array_object(playback_devices_o, m_playback);
+ cout << " ]" << endl;
+}
+
+void CDeviceMapParser::parse_capture()
+{
+ json_object *capture_devices_o = nullptr;
+
+ if (!json_object_object_get_ex(m_json_device_files_obj, DEVICE_TYPE_PROP_CAPTURE_DEVICES, &capture_devices_o)) {
+ cout << "failed to get capture" << endl;
+ return;
+ }
+
+ cout << " " << DEVICE_TYPE_PROP_CAPTURE_DEVICES << " : [" << endl;
+ parse_device_file_array_object(capture_devices_o, m_capture);
+ cout << " ]" << endl;
+}
+
+void CDeviceMapParser::get_device(string& s, string& card, string& device_num)
+{
+ // eg. alsa:0,0
+ string delimiter = ",";
+ string s1(s.substr(s.find_last_of(':') + 1));
+
+ // eg. 0,0
+ size_t pos = s1.find(delimiter);
+ string token(s1.substr(0, pos));
+ s1.erase(0, pos + delimiter.length());
+
+ card.assign(token);
+ device_num.assign(s1);
+}
+
+void CDeviceMapParser::get_single_param(string& s, int& rate, int& channels)
+{
+ // eg. rate=44100
+ string delimiter = "=";
+ size_t pos = s.find(delimiter);
+ string token = s.substr(0, pos);
+ s.erase(0, pos + delimiter.length());
+
+ if (token.compare("rate") == 0)
+ rate = stoi(s);
+ else if (token.compare("channels") == 0)
+ channels = stoi(s);
+}
+
+void CDeviceMapParser::get_params(string& s, int& rate, int& channels)
+{
+ // eg. rate=44100 channels=1
+ string delimiter = " ";
+ size_t pos = 0;
+ string token;
+ string s1(s);
+
+ while ((pos = s1.find(delimiter)) != string::npos) {
+ token = s1.substr(0, pos);
+ get_single_param(token, rate, channels);
+ s1.erase(0, pos + delimiter.length());
+ }
+ get_single_param(s1, rate, channels);
+}
+
+
+void CDeviceMapParser::dump_devices()
+{
+ string card, device_num;
+ int rate = -1, channels = -1;
+
+ get_playback(card, device_num, rate, channels);
+ get_capture(card, device_num, rate, channels);
+}
+
+void CDeviceMapParser::get_playback(string& card, string& device_num, int& rate, int& channels)
+{
+ parse_playback();
+
+ get_device(m_playback.first, card, device_num);
+ get_params(m_playback.second, rate, channels);
+ cout << " 1. PLAYBACK" << endl;
+ cout << " > card=" << card << ", device=" << device_num << endl;
+ cout << " > rate=" << rate << ", channels=" << channels << endl << endl;
+}
+
+void CDeviceMapParser::get_capture(string& card, string& device_num, int& rate, int& channels)
+{
+ parse_capture();
+
+ get_device(m_capture.first, card, device_num);
+ get_params(m_capture.second, rate, channels);
+ cout << " 2. CAPTURE" << endl;
+ cout << " > card=" << card << ", device=" << device_num << endl;
+ cout << " > rate=" << rate << ", channels=" << channels << endl;
+}
+
+void CDeviceMapParser::parse_device_string_object(json_object *device_string_o, string& device_string)
+{
+ assert(device_string_o);
+ assert(json_object_is_type(device_string_o, json_type_string));
+
+ // object example
+ // device-string : alsa:sprdphone,0,
+
+ device_string.assign(json_object_get_string(device_string_o));
+
+ cout << " " << DEVICE_TYPE_PROP_DEVICE_STRING << " : " << device_string << "," << endl;
+}
+
+void CDeviceMapParser::parse_device_role_object(json_object *device_role_o, string& device_params)
+{
+ struct json_object_iterator it, it_end;
+
+ assert(device_role_o);
+ assert(json_object_is_type(device_role_o, json_type_object));
+
+ // <object example>
+ // role : { normal : rate=44100 }
+
+ it = json_object_iter_begin(device_role_o);
+ it_end = json_object_iter_end(device_role_o);
+
+ while (!json_object_iter_equal(&it, &it_end)) {
+ if (strcmp(json_object_iter_peek_name(&it), "normal") == 0) {
+ device_params.assign(json_object_get_string(json_object_iter_peek_value(&it)));
+ cout << " " << DEVICE_TYPE_PROP_ROLE << " : { normal : " << device_params << " }" << endl;
+ break;
+ }
+
+ json_object_iter_next(&it);
+ }
+}
+
+void CDeviceMapParser::parse_device_file_object(json_object *device_file_o, pair<string, string>& device)
+{
+ json_object *device_file_prop_o = nullptr;
+ string device_string, device_param;
+
+ assert(device_file_o);
+ assert(json_object_is_type(device_file_o, json_type_object));
+
+ // <object example>
+ // device-string : alsa:sprdphone,0,
+ // role : { normal : rate=44100 }
+
+ // parse role
+ if (!json_object_object_get_ex(device_file_o, DEVICE_TYPE_PROP_ROLE, &device_file_prop_o)) {
+ cout << "Get device role object failed" << endl;
+ return;
+ }
+ parse_device_role_object(device_file_prop_o, device_param);
+
+ if (device_param.empty()) {
+ cout << " " << "[E] This is not a normal device..skip" << endl;
+ return;
+ }
+
+ // parse device-string
+ if (!json_object_object_get_ex(device_file_o, DEVICE_TYPE_PROP_DEVICE_STRING, &device_file_prop_o)) {
+ cout << "Get device-string object failed" << endl;
+ return;
+ }
+ parse_device_string_object(device_file_prop_o, device_string);
+
+ // store device information
+ device = make_pair(device_string, device_param);
+}
+
+void CDeviceMapParser::parse_device_file_array_object(json_object *device_file_array_o, pair<string, string>& device)
+{
+ int num, idx;
+ json_object *device_file_o = nullptr;
+
+ assert(device_file_array_o);
+ assert(json_object_is_type(device_file_array_o, json_type_array));
+
+ // <object example>
+ // {
+ // device-string : alsa:sprdphone,0,
+ // role : { normal : rate=44100 }
+ // }
+
+ // ToDo : this might be replaced with iterator such as foreach?
+ num = json_object_array_length(device_file_array_o);
+ for (idx = 0; idx < num; idx++) {
+ if (!(device_file_o = json_object_array_get_idx(device_file_array_o, idx))) {
+ cout << "Get device file object failed" << endl;
+ return;
+ }
+
+ cout << " {" << endl;
+ parse_device_file_object(device_file_o, device);
+ cout << " }" << endl;
+ }
+}