xref: /aosp_15_r20/system/extras/tests/audio/alsa/pcmtest.cpp (revision 288bf5226967eb3dac5cce6c939ccc2a7f2b4fe5)
1*288bf522SAndroid Build Coastguard Worker /*
2*288bf522SAndroid Build Coastguard Worker  * Copyright (C) 2013 The Android Open Source Project
3*288bf522SAndroid Build Coastguard Worker  *
4*288bf522SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*288bf522SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*288bf522SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*288bf522SAndroid Build Coastguard Worker  *
8*288bf522SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*288bf522SAndroid Build Coastguard Worker  *
10*288bf522SAndroid Build Coastguard Worker  * Unless requied by applicable law or agreed to in writing, software
11*288bf522SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*288bf522SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*288bf522SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*288bf522SAndroid Build Coastguard Worker  * limitations under the License.
15*288bf522SAndroid Build Coastguard Worker  *
16*288bf522SAndroid Build Coastguard Worker  */
17*288bf522SAndroid Build Coastguard Worker 
18*288bf522SAndroid Build Coastguard Worker #include <assert.h>
19*288bf522SAndroid Build Coastguard Worker #include <dirent.h>
20*288bf522SAndroid Build Coastguard Worker #include <errno.h>
21*288bf522SAndroid Build Coastguard Worker #include <fcntl.h>
22*288bf522SAndroid Build Coastguard Worker #include <stdio.h>
23*288bf522SAndroid Build Coastguard Worker #include <stdlib.h>
24*288bf522SAndroid Build Coastguard Worker #include <gtest/gtest.h>
25*288bf522SAndroid Build Coastguard Worker #include <linux/ioctl.h>
26*288bf522SAndroid Build Coastguard Worker #include <sound/asound.h>
27*288bf522SAndroid Build Coastguard Worker #include <sys/types.h>
28*288bf522SAndroid Build Coastguard Worker #include <tinyalsa/asoundlib.h>
29*288bf522SAndroid Build Coastguard Worker 
30*288bf522SAndroid Build Coastguard Worker #define LOG_TAG "pcmtest"
31*288bf522SAndroid Build Coastguard Worker #include <utils/Log.h>
32*288bf522SAndroid Build Coastguard Worker 
33*288bf522SAndroid Build Coastguard Worker #define PCM_PREFIX	"pcm"
34*288bf522SAndroid Build Coastguard Worker #define MIXER_PREFIX	"control"
35*288bf522SAndroid Build Coastguard Worker #define TIMER_PREFIX	"timer"
36*288bf522SAndroid Build Coastguard Worker 
37*288bf522SAndroid Build Coastguard Worker #define MAXSTR 200
38*288bf522SAndroid Build Coastguard Worker #define testPrintI(...)                 \
39*288bf522SAndroid Build Coastguard Worker     do {                                \
40*288bf522SAndroid Build Coastguard Worker         testPrint(stdout, __VA_ARGS__); \
41*288bf522SAndroid Build Coastguard Worker     } while (0)
42*288bf522SAndroid Build Coastguard Worker 
43*288bf522SAndroid Build Coastguard Worker const char kSoundDir[] = "/dev/snd";
44*288bf522SAndroid Build Coastguard Worker 
45*288bf522SAndroid Build Coastguard Worker typedef struct PCM_NODE {
46*288bf522SAndroid Build Coastguard Worker     unsigned int card;
47*288bf522SAndroid Build Coastguard Worker     unsigned int device;
48*288bf522SAndroid Build Coastguard Worker     unsigned int flags;
49*288bf522SAndroid Build Coastguard Worker } pcm_node_t;
50*288bf522SAndroid Build Coastguard Worker 
51*288bf522SAndroid Build Coastguard Worker static pcm_node_t *pcmnodes;
52*288bf522SAndroid Build Coastguard Worker 
53*288bf522SAndroid Build Coastguard Worker static unsigned int pcms;
54*288bf522SAndroid Build Coastguard Worker static unsigned int cards;
55*288bf522SAndroid Build Coastguard Worker static unsigned int mixers;
56*288bf522SAndroid Build Coastguard Worker static unsigned int timers;
57*288bf522SAndroid Build Coastguard Worker 
testPrint(FILE * stream,const char * fmt,...)58*288bf522SAndroid Build Coastguard Worker void testPrint(FILE* stream, const char* fmt, ...) {
59*288bf522SAndroid Build Coastguard Worker     char line[MAXSTR];
60*288bf522SAndroid Build Coastguard Worker     va_list args;
61*288bf522SAndroid Build Coastguard Worker 
62*288bf522SAndroid Build Coastguard Worker     va_start(args, fmt);
63*288bf522SAndroid Build Coastguard Worker     vsnprintf(line, sizeof(line), fmt, args);
64*288bf522SAndroid Build Coastguard Worker     if (stream == stderr) {
65*288bf522SAndroid Build Coastguard Worker         ALOG(LOG_ERROR, LOG_TAG, "%s", line);
66*288bf522SAndroid Build Coastguard Worker     } else {
67*288bf522SAndroid Build Coastguard Worker         ALOG(LOG_INFO, LOG_TAG, "%s", line);
68*288bf522SAndroid Build Coastguard Worker     }
69*288bf522SAndroid Build Coastguard Worker     vfprintf(stream, fmt, args);
70*288bf522SAndroid Build Coastguard Worker     va_end(args);
71*288bf522SAndroid Build Coastguard Worker     fputc('\n', stream);
72*288bf522SAndroid Build Coastguard Worker }
73*288bf522SAndroid Build Coastguard Worker 
getPcmNodes(void)74*288bf522SAndroid Build Coastguard Worker unsigned int getPcmNodes(void)
75*288bf522SAndroid Build Coastguard Worker {
76*288bf522SAndroid Build Coastguard Worker     DIR *d;
77*288bf522SAndroid Build Coastguard Worker     struct dirent *de;
78*288bf522SAndroid Build Coastguard Worker     unsigned int pcount = 0;
79*288bf522SAndroid Build Coastguard Worker 
80*288bf522SAndroid Build Coastguard Worker     d = opendir(kSoundDir);
81*288bf522SAndroid Build Coastguard Worker     if (d == 0)
82*288bf522SAndroid Build Coastguard Worker         return 0;
83*288bf522SAndroid Build Coastguard Worker     while ((de = readdir(d)) != NULL) {
84*288bf522SAndroid Build Coastguard Worker         if (de->d_name[0] == '.')
85*288bf522SAndroid Build Coastguard Worker             continue;
86*288bf522SAndroid Build Coastguard Worker         if (strstr(de->d_name, PCM_PREFIX))
87*288bf522SAndroid Build Coastguard Worker             pcount++;
88*288bf522SAndroid Build Coastguard Worker     }
89*288bf522SAndroid Build Coastguard Worker     closedir(d);
90*288bf522SAndroid Build Coastguard Worker     return pcount;
91*288bf522SAndroid Build Coastguard Worker }
92*288bf522SAndroid Build Coastguard Worker 
getSndDev(unsigned int pcmdevs)93*288bf522SAndroid Build Coastguard Worker int getSndDev(unsigned int pcmdevs)
94*288bf522SAndroid Build Coastguard Worker {
95*288bf522SAndroid Build Coastguard Worker     DIR *d;
96*288bf522SAndroid Build Coastguard Worker     struct dirent *de;
97*288bf522SAndroid Build Coastguard Worker     unsigned int prevcard = -1;
98*288bf522SAndroid Build Coastguard Worker 
99*288bf522SAndroid Build Coastguard Worker     d = opendir(kSoundDir);
100*288bf522SAndroid Build Coastguard Worker     if (d == 0)
101*288bf522SAndroid Build Coastguard Worker         return -ENXIO;
102*288bf522SAndroid Build Coastguard Worker     pcmnodes = (pcm_node_t *)malloc(pcmdevs * sizeof(pcm_node_t));
103*288bf522SAndroid Build Coastguard Worker     if (!pcmnodes)
104*288bf522SAndroid Build Coastguard Worker         return -ENOMEM;
105*288bf522SAndroid Build Coastguard Worker     pcms = 0;
106*288bf522SAndroid Build Coastguard Worker     while ((de = readdir(d)) != NULL) {
107*288bf522SAndroid Build Coastguard Worker         if (de->d_name[0] == '.')
108*288bf522SAndroid Build Coastguard Worker             continue;
109*288bf522SAndroid Build Coastguard Worker         /* printf("%s\n", de->d_name); */
110*288bf522SAndroid Build Coastguard Worker         if (strstr(de->d_name, PCM_PREFIX)) {
111*288bf522SAndroid Build Coastguard Worker             char flags;
112*288bf522SAndroid Build Coastguard Worker 
113*288bf522SAndroid Build Coastguard Worker             EXPECT_LE(pcms, pcmdevs) << "Too many PCMs";
114*288bf522SAndroid Build Coastguard Worker             if (pcms >= pcmdevs)
115*288bf522SAndroid Build Coastguard Worker                 continue;
116*288bf522SAndroid Build Coastguard Worker             sscanf(de->d_name, PCM_PREFIX "C%uD%u", &(pcmnodes[pcms].card),
117*288bf522SAndroid Build Coastguard Worker                    &(pcmnodes[pcms].device));
118*288bf522SAndroid Build Coastguard Worker             flags = de->d_name[strlen(de->d_name)-1];
119*288bf522SAndroid Build Coastguard Worker             if (flags == 'c') {
120*288bf522SAndroid Build Coastguard Worker                 pcmnodes[pcms].flags = PCM_IN;
121*288bf522SAndroid Build Coastguard Worker             } else if(flags == 'p') {
122*288bf522SAndroid Build Coastguard Worker                 pcmnodes[pcms].flags = PCM_OUT;
123*288bf522SAndroid Build Coastguard Worker             } else {
124*288bf522SAndroid Build Coastguard Worker                 pcmnodes[pcms].flags = -1;
125*288bf522SAndroid Build Coastguard Worker                 testPrintI("Unknown PCM type = %c", flags);
126*288bf522SAndroid Build Coastguard Worker             }
127*288bf522SAndroid Build Coastguard Worker             if (prevcard != pcmnodes[pcms].card)
128*288bf522SAndroid Build Coastguard Worker                 cards++;
129*288bf522SAndroid Build Coastguard Worker             prevcard = pcmnodes[pcms].card;
130*288bf522SAndroid Build Coastguard Worker             pcms++;
131*288bf522SAndroid Build Coastguard Worker             continue;
132*288bf522SAndroid Build Coastguard Worker         }
133*288bf522SAndroid Build Coastguard Worker         if (strstr(de->d_name, MIXER_PREFIX)) {
134*288bf522SAndroid Build Coastguard Worker             unsigned int mixer = -1;
135*288bf522SAndroid Build Coastguard Worker             sscanf(de->d_name, MIXER_PREFIX "C%u", &mixer);
136*288bf522SAndroid Build Coastguard Worker             mixers++;
137*288bf522SAndroid Build Coastguard Worker             continue;
138*288bf522SAndroid Build Coastguard Worker         }
139*288bf522SAndroid Build Coastguard Worker         if (strstr(de->d_name, TIMER_PREFIX)) {
140*288bf522SAndroid Build Coastguard Worker             timers++;
141*288bf522SAndroid Build Coastguard Worker             continue;
142*288bf522SAndroid Build Coastguard Worker         }
143*288bf522SAndroid Build Coastguard Worker     }
144*288bf522SAndroid Build Coastguard Worker     closedir(d);
145*288bf522SAndroid Build Coastguard Worker     return 0;
146*288bf522SAndroid Build Coastguard Worker }
147*288bf522SAndroid Build Coastguard Worker 
getPcmParams(unsigned int i)148*288bf522SAndroid Build Coastguard Worker int getPcmParams(unsigned int i)
149*288bf522SAndroid Build Coastguard Worker {
150*288bf522SAndroid Build Coastguard Worker     struct pcm_params *params;
151*288bf522SAndroid Build Coastguard Worker     unsigned int min;
152*288bf522SAndroid Build Coastguard Worker     unsigned int max;
153*288bf522SAndroid Build Coastguard Worker 
154*288bf522SAndroid Build Coastguard Worker     params = pcm_params_get(pcmnodes[i].card, pcmnodes[i].device,
155*288bf522SAndroid Build Coastguard Worker                             pcmnodes[i].flags);
156*288bf522SAndroid Build Coastguard Worker     if (params == NULL)
157*288bf522SAndroid Build Coastguard Worker         return -ENODEV;
158*288bf522SAndroid Build Coastguard Worker 
159*288bf522SAndroid Build Coastguard Worker     min = pcm_params_get_min(params, PCM_PARAM_RATE);
160*288bf522SAndroid Build Coastguard Worker     max = pcm_params_get_max(params, PCM_PARAM_RATE);
161*288bf522SAndroid Build Coastguard Worker     EXPECT_LE(min, max);
162*288bf522SAndroid Build Coastguard Worker     /* printf("        Rate:\tmin=%uHz\tmax=%uHz\n", min, max); */
163*288bf522SAndroid Build Coastguard Worker     min = pcm_params_get_min(params, PCM_PARAM_CHANNELS);
164*288bf522SAndroid Build Coastguard Worker     max = pcm_params_get_max(params, PCM_PARAM_CHANNELS);
165*288bf522SAndroid Build Coastguard Worker     EXPECT_LE(min, max);
166*288bf522SAndroid Build Coastguard Worker     /* printf("    Channels:\tmin=%u\t\tmax=%u\n", min, max); */
167*288bf522SAndroid Build Coastguard Worker     min = pcm_params_get_min(params, PCM_PARAM_SAMPLE_BITS);
168*288bf522SAndroid Build Coastguard Worker     max = pcm_params_get_max(params, PCM_PARAM_SAMPLE_BITS);
169*288bf522SAndroid Build Coastguard Worker     EXPECT_LE(min, max);
170*288bf522SAndroid Build Coastguard Worker     /* printf(" Sample bits:\tmin=%u\t\tmax=%u\n", min, max); */
171*288bf522SAndroid Build Coastguard Worker     min = pcm_params_get_min(params, PCM_PARAM_PERIOD_SIZE);
172*288bf522SAndroid Build Coastguard Worker     max = pcm_params_get_max(params, PCM_PARAM_PERIOD_SIZE);
173*288bf522SAndroid Build Coastguard Worker     EXPECT_LE(min, max);
174*288bf522SAndroid Build Coastguard Worker     /* printf(" Period size:\tmin=%u\t\tmax=%u\n", min, max); */
175*288bf522SAndroid Build Coastguard Worker     min = pcm_params_get_min(params, PCM_PARAM_PERIODS);
176*288bf522SAndroid Build Coastguard Worker     max = pcm_params_get_max(params, PCM_PARAM_PERIODS);
177*288bf522SAndroid Build Coastguard Worker     EXPECT_LE(min, max);
178*288bf522SAndroid Build Coastguard Worker     /* printf("Period count:\tmin=%u\t\tmax=%u\n", min, max); */
179*288bf522SAndroid Build Coastguard Worker 
180*288bf522SAndroid Build Coastguard Worker     pcm_params_free(params);
181*288bf522SAndroid Build Coastguard Worker     return 0;
182*288bf522SAndroid Build Coastguard Worker }
183*288bf522SAndroid Build Coastguard Worker 
TEST(pcmtest,CheckAudioDir)184*288bf522SAndroid Build Coastguard Worker TEST(pcmtest, CheckAudioDir) {
185*288bf522SAndroid Build Coastguard Worker     pcms = getPcmNodes();
186*288bf522SAndroid Build Coastguard Worker     ASSERT_GT(pcms, 0U);
187*288bf522SAndroid Build Coastguard Worker }
188*288bf522SAndroid Build Coastguard Worker 
TEST(pcmtest,GetSoundDevs)189*288bf522SAndroid Build Coastguard Worker TEST(pcmtest, GetSoundDevs) {
190*288bf522SAndroid Build Coastguard Worker     int err = getSndDev(pcms);
191*288bf522SAndroid Build Coastguard Worker     testPrintI(" DEVICES = PCMS:%u CARDS:%u MIXERS:%u TIMERS:%u",
192*288bf522SAndroid Build Coastguard Worker                pcms, cards, mixers, timers);
193*288bf522SAndroid Build Coastguard Worker     ASSERT_EQ(0, err);
194*288bf522SAndroid Build Coastguard Worker }
195*288bf522SAndroid Build Coastguard Worker 
TEST(pcmtest,CheckPcmSanity0)196*288bf522SAndroid Build Coastguard Worker TEST(pcmtest, CheckPcmSanity0) {
197*288bf522SAndroid Build Coastguard Worker     ASSERT_NE(0U, pcms);
198*288bf522SAndroid Build Coastguard Worker }
199*288bf522SAndroid Build Coastguard Worker 
TEST(pcmtest,CheckPcmSanity1)200*288bf522SAndroid Build Coastguard Worker TEST(pcmtest, CheckPcmSanity1) {
201*288bf522SAndroid Build Coastguard Worker     EXPECT_NE(1U, pcms % 2);
202*288bf522SAndroid Build Coastguard Worker }
203*288bf522SAndroid Build Coastguard Worker 
TEST(pcmtests,CheckMixerSanity)204*288bf522SAndroid Build Coastguard Worker TEST(pcmtests, CheckMixerSanity) {
205*288bf522SAndroid Build Coastguard Worker     ASSERT_NE(0U, mixers);
206*288bf522SAndroid Build Coastguard Worker     ASSERT_EQ(mixers, cards);
207*288bf522SAndroid Build Coastguard Worker }
208*288bf522SAndroid Build Coastguard Worker 
TEST(pcmtest,CheckTimesSanity0)209*288bf522SAndroid Build Coastguard Worker TEST(pcmtest, CheckTimesSanity0) {
210*288bf522SAndroid Build Coastguard Worker     ASSERT_NE(0U, timers);
211*288bf522SAndroid Build Coastguard Worker }
212*288bf522SAndroid Build Coastguard Worker 
TEST(pcmtest,CheckTimesSanity1)213*288bf522SAndroid Build Coastguard Worker TEST(pcmtest, CheckTimesSanity1) {
214*288bf522SAndroid Build Coastguard Worker     EXPECT_EQ(1U, timers);
215*288bf522SAndroid Build Coastguard Worker }
216*288bf522SAndroid Build Coastguard Worker 
TEST(pcmtest,CheckPcmDevices)217*288bf522SAndroid Build Coastguard Worker TEST(pcmtest, CheckPcmDevices) {
218*288bf522SAndroid Build Coastguard Worker     for (unsigned int i = 0; i < pcms; i++) {
219*288bf522SAndroid Build Coastguard Worker         EXPECT_EQ(0, getPcmParams(i));
220*288bf522SAndroid Build Coastguard Worker     }
221*288bf522SAndroid Build Coastguard Worker     free(pcmnodes);
222*288bf522SAndroid Build Coastguard Worker }
223*288bf522SAndroid Build Coastguard Worker 
TEST(pcmtest,CheckMixerDevices)224*288bf522SAndroid Build Coastguard Worker TEST(pcmtest, CheckMixerDevices) {
225*288bf522SAndroid Build Coastguard Worker     struct mixer *mixer;
226*288bf522SAndroid Build Coastguard Worker     for (unsigned int i = 0; i < mixers; i++) {
227*288bf522SAndroid Build Coastguard Worker          mixer = mixer_open(i);
228*288bf522SAndroid Build Coastguard Worker          EXPECT_TRUE(mixer != NULL);
229*288bf522SAndroid Build Coastguard Worker          if (mixer)
230*288bf522SAndroid Build Coastguard Worker              mixer_close(mixer);
231*288bf522SAndroid Build Coastguard Worker     }
232*288bf522SAndroid Build Coastguard Worker }
233*288bf522SAndroid Build Coastguard Worker 
TEST(pcmtest,CheckTimer)234*288bf522SAndroid Build Coastguard Worker TEST(pcmtest, CheckTimer) {
235*288bf522SAndroid Build Coastguard Worker     int ver = 0;
236*288bf522SAndroid Build Coastguard Worker     int fd = open("/dev/snd/timer", O_RDWR | O_NONBLOCK);
237*288bf522SAndroid Build Coastguard Worker     ASSERT_GE(fd, 0);
238*288bf522SAndroid Build Coastguard Worker     int ret = ioctl(fd, SNDRV_TIMER_IOCTL_PVERSION, &ver);
239*288bf522SAndroid Build Coastguard Worker     EXPECT_EQ(0, ret);
240*288bf522SAndroid Build Coastguard Worker     testPrintI(" Timer Version = 0x%x", ver);
241*288bf522SAndroid Build Coastguard Worker     close(fd);
242*288bf522SAndroid Build Coastguard Worker }
243