1 /*
2  * Copyright 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <bluetooth/log.h>
18 #include <gtest/gtest.h>
19 
20 #include <cstdint>
21 #include <string>
22 
23 #include "hardware/bt_av.h"
24 #include "stack/include/a2dp_codec_api.h"
25 #include "stack/include/a2dp_constants.h"
26 #include "stack/include/a2dp_vendor_aptx_constants.h"
27 #include "stack/include/a2dp_vendor_aptx_hd_constants.h"
28 #include "stack/include/a2dp_vendor_ldac_constants.h"
29 #include "stack/include/a2dp_vendor_opus_constants.h"
30 #include "stack/include/avdt_api.h"
31 
32 namespace {
33 static constexpr uint8_t kCodecCapabilitiesWithTruncatedMediaCodecType[] = {0x0};
34 static constexpr uint8_t kCodecCapabilitiesWithTruncatedVendorCodecId[] = {0x5, 0x0, 0xff,
35                                                                            0x1, 0x2, 0x3};
36 static constexpr uint8_t kCodecCapabilitiesWithInvalidMediaCodecType[] = {0x2, 0x0, 0xaa};
37 static constexpr uint8_t kCodecCapabilitiesWithInvalidVendorCodecId[] = {0x8, 0x0, 0xff, 0x1, 0x2,
38                                                                          0x3, 0x4, 0x5,  0x6};
39 
40 static constexpr uint8_t kSbcCodecCapabilities[] = {
41         6,                   // Length (A2DP_SBC_INFO_LEN)
42         0,                   // Media Type: AVDT_MEDIA_TYPE_AUDIO
43         0,                   // Media Codec Type: A2DP_MEDIA_CT_SBC
44         0x20 | 0x01,         // Sample Frequency: A2DP_SBC_IE_SAMP_FREQ_44 |
45                              // Channel Mode: A2DP_SBC_IE_CH_MD_JOINT
46         0x10 | 0x04 | 0x01,  // Block Length: A2DP_SBC_IE_BLOCKS_16 |
47                              // Subbands: A2DP_SBC_IE_SUBBAND_8 |
48                              // Allocation Method: A2DP_SBC_IE_ALLOC_MD_L
49         2,                   // MinimumBitpool Value: A2DP_SBC_IE_MIN_BITPOOL
50         53,                  // Maximum Bitpool Value: A2DP_SBC_MAX_BITPOOL
51         7,                   // Fake
52         8,                   // Fake
53         9                    // Fake
54 };
55 
56 static constexpr uint8_t kAacCodecCapabilities[] = {
57         8,           // Length (A2DP_AAC_INFO_LEN)
58         0,           // Media Type: AVDT_MEDIA_TYPE_AUDIO
59         2,           // Media Codec Type: A2DP_MEDIA_CT_AAC
60         0x80,        // Object Type: A2DP_AAC_OBJECT_TYPE_MPEG2_LC
61         0x01,        // Sampling Frequency: A2DP_AAC_SAMPLING_FREQ_44100
62         0x04,        // Channels: A2DP_AAC_CHANNEL_MODE_STEREO
63         0x00 | 0x4,  // Variable Bit Rate:
64                      // A2DP_AAC_VARIABLE_BIT_RATE_DISABLED
65                      // Bit Rate: 320000 = 0x4e200
66         0xe2,        // Bit Rate: 320000 = 0x4e200
67         0x00,        // Bit Rate: 320000 = 0x4e200
68         7,           // Unused
69         8,           // Unused
70         9            // Unused
71 };
72 
73 static constexpr uint8_t kAptxCodecCapabilities[] = {
74         A2DP_APTX_CODEC_LEN,
75         AVDT_MEDIA_TYPE_AUDIO,
76         A2DP_MEDIA_CT_NON_A2DP,
77         0x4F,  // A2DP_APTX_VENDOR_ID
78         0x00,  // A2DP_APTX_VENDOR_ID
79         0x00,  // A2DP_APTX_VENDOR_ID
80         0x00,  // A2DP_APTX_VENDOR_ID
81         0x01,  // A2DP_APTX_CODEC_ID
82         0x00,  // A2DP_APTX_CODEC_ID,
83         A2DP_APTX_SAMPLERATE_44100 | A2DP_APTX_CHANNELS_STEREO,
84 };
85 
86 static constexpr uint8_t kAptxHdCodecCapabilities[] = {
87         A2DP_APTX_HD_CODEC_LEN,
88         AVDT_MEDIA_TYPE_AUDIO,
89         A2DP_MEDIA_CT_NON_A2DP,
90         0xD7,  // A2DP_APTX_HD_VENDOR_ID
91         0x00,  // A2DP_APTX_HD_VENDOR_ID
92         0x00,  // A2DP_APTX_HD_VENDOR_ID
93         0x00,  // A2DP_APTX_HD_VENDOR_ID
94         0x24,  // A2DP_APTX_HD_CODEC_ID
95         0x00,  // A2DP_APTX_HD_CODEC_ID,
96         A2DP_APTX_HD_SAMPLERATE_44100 | A2DP_APTX_HD_CHANNELS_STEREO,
97         A2DP_APTX_HD_ACL_SPRINT_RESERVED0,
98         A2DP_APTX_HD_ACL_SPRINT_RESERVED1,
99         A2DP_APTX_HD_ACL_SPRINT_RESERVED2,
100         A2DP_APTX_HD_ACL_SPRINT_RESERVED3,
101 };
102 
103 static constexpr uint8_t kLdacCodecCapabilities[] = {
104         A2DP_LDAC_CODEC_LEN,
105         AVDT_MEDIA_TYPE_AUDIO,
106         A2DP_MEDIA_CT_NON_A2DP,
107         0x2D,  // A2DP_LDAC_VENDOR_ID
108         0x01,  // A2DP_LDAC_VENDOR_ID
109         0x00,  // A2DP_LDAC_VENDOR_ID
110         0x00,  // A2DP_LDAC_VENDOR_ID
111         0xAA,  // A2DP_LDAC_CODEC_ID
112         0x00,  // A2DP_LDAC_CODEC_ID,
113         A2DP_LDAC_SAMPLING_FREQ_44100,
114         A2DP_LDAC_CHANNEL_MODE_STEREO,
115 };
116 
117 static constexpr uint8_t kOpusCodecCapabilities[] = {
118         A2DP_OPUS_CODEC_LEN,         // Length
119         AVDT_MEDIA_TYPE_AUDIO << 4,  // Media Type
120         A2DP_MEDIA_CT_NON_A2DP,      // Media Codec Type Vendor
121         (A2DP_OPUS_VENDOR_ID & 0x000000FF),
122         (A2DP_OPUS_VENDOR_ID & 0x0000FF00) >> 8,
123         (A2DP_OPUS_VENDOR_ID & 0x00FF0000) >> 16,
124         (A2DP_OPUS_VENDOR_ID & 0xFF000000) >> 24,
125         (A2DP_OPUS_CODEC_ID & 0x00FF),
126         (A2DP_OPUS_CODEC_ID & 0xFF00) >> 8,
127         A2DP_OPUS_CHANNEL_MODE_STEREO | A2DP_OPUS_20MS_FRAMESIZE | A2DP_OPUS_SAMPLING_FREQ_48000,
128 };
129 }  // namespace
130 
131 namespace bluetooth::a2dp {
132 
133 class MediaCodecCapabilitiesTest : public ::testing::Test {};
134 
135 // Test the correctness of the method `bluetooth::a2dp::ParseCodecId`.
TEST_F(MediaCodecCapabilitiesTest,ParseCodecId)136 TEST_F(MediaCodecCapabilitiesTest, ParseCodecId) {
137   ASSERT_EQ(ParseCodecId(kCodecCapabilitiesWithTruncatedMediaCodecType), std::nullopt);
138   ASSERT_EQ(ParseCodecId(kCodecCapabilitiesWithTruncatedVendorCodecId), std::nullopt);
139   ASSERT_EQ(ParseCodecId(kCodecCapabilitiesWithInvalidMediaCodecType), std::nullopt);
140   ASSERT_EQ(ParseCodecId(kCodecCapabilitiesWithInvalidVendorCodecId), std::nullopt);
141 
142   ASSERT_EQ(ParseCodecId(kSbcCodecCapabilities), CodecId::SBC);
143   ASSERT_EQ(ParseCodecId(kAacCodecCapabilities), CodecId::AAC);
144   ASSERT_EQ(ParseCodecId(kAptxCodecCapabilities), CodecId::APTX);
145   ASSERT_EQ(ParseCodecId(kAptxHdCodecCapabilities), CodecId::APTX_HD);
146   ASSERT_EQ(ParseCodecId(kLdacCodecCapabilities), CodecId::LDAC);
147   ASSERT_EQ(ParseCodecId(kOpusCodecCapabilities), CodecId::OPUS);
148 }
149 
150 // Test provided to validate the Media Codec Capabilities, the legacy APIs `A2DP_xxx`
151 // are considered the source of truth here.
TEST_F(MediaCodecCapabilitiesTest,A2DP_SourceCodecIndex)152 TEST_F(MediaCodecCapabilitiesTest, A2DP_SourceCodecIndex) {
153   ASSERT_EQ(A2DP_SourceCodecIndex(kSbcCodecCapabilities), BTAV_A2DP_CODEC_INDEX_SOURCE_SBC);
154   ASSERT_EQ(A2DP_SourceCodecIndex(kAacCodecCapabilities), BTAV_A2DP_CODEC_INDEX_SOURCE_AAC);
155   ASSERT_EQ(A2DP_SourceCodecIndex(kAptxCodecCapabilities), BTAV_A2DP_CODEC_INDEX_SOURCE_APTX);
156   ASSERT_EQ(A2DP_SourceCodecIndex(kAptxHdCodecCapabilities), BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD);
157   ASSERT_EQ(A2DP_SourceCodecIndex(kLdacCodecCapabilities), BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC);
158   ASSERT_EQ(A2DP_SourceCodecIndex(kOpusCodecCapabilities), BTAV_A2DP_CODEC_INDEX_SOURCE_OPUS);
159 }
160 
161 }  // namespace bluetooth::a2dp
162