diff --git a/ci/build_dependencies.sh b/ci/build_dependencies.sh index 9abff1c9..408e91fb 100644 --- a/ci/build_dependencies.sh +++ b/ci/build_dependencies.sh @@ -43,22 +43,19 @@ apt install -y \ uuid-dev \ libevdev-dev \ libdrm-dev \ - libsafec-dev \ + libbsd-dev \ + gperf \ python3-pip python3 -m pip install jsonref ########################################### # 2. Clone the required repositories -XRSDK_REF="1.0.13" -git clone --depth 1 --filter=blob:none --branch "${XRSDK_REF}" https://github.com/rdkcentral/xr-voice-sdk.git +# Will uncomment the following lines and update the branch to main once the changes in feature/RDKEMW-18082 are merged and released. +# git clone --depth 1 --filter=blob:none https://github.com/rdkcentral/xr-voice-sdk.git +git clone --depth 1 --filter=blob:none --branch feature/RDKEMW-18082 https://github.com/rdkcentral/xr-voice-sdk.git -git clone --depth 1 --filter=blob:none --branch develop https://github.com/rdkcentral/entservices-testframework.git - -# Patch the upstream testframework devicesettings.h with ctrlm-specific -# additions (ducking types, setAudioDucking, Manager::IsInitialized). -# We can remove this if added to upstream testframework -git -C entservices-testframework apply "$GITHUB_WORKSPACE/ci/mocks/devicesettings_ctrlm.patch" +git clone --depth 1 --filter=blob:none https://github.com/rdkcentral/entservices-testframework.git git clone --depth 1 --filter=blob:none --sparse --branch develop https://github.com/rdkcentral/iarmmgrs.git git -C iarmmgrs sparse-checkout set hal @@ -72,10 +69,14 @@ git -C rdk-halif-power_manager sparse-checkout set include git clone --depth 1 --filter=blob:none --sparse --branch develop https://github.com/rdkcentral/rdkversion.git git -C rdkversion sparse-checkout set src +git clone --depth 1 --filter=blob:none --sparse https://github.com/rdkcentral/meta-rdk-oss-reference.git +git -C meta-rdk-oss-reference sparse-checkout set recipes-common/safec-common-wrapper/files + IARMMGRS_DIR="$GITHUB_WORKSPACE/iarmmgrs" DEEPSLEEP_HAL_DIR="$GITHUB_WORKSPACE/rdk-halif-deepsleep_manager" POWER_HAL_DIR="$GITHUB_WORKSPACE/rdk-halif-power_manager" RDKVERSION_DIR="$GITHUB_WORKSPACE/rdkversion" +SAFEC_WRAPPER_DIR="$GITHUB_WORKSPACE/meta-rdk-oss-reference/recipes-common/safec-common-wrapper/files" ############################ # 3. Create stub/empty headers for external dependencies @@ -83,30 +84,48 @@ echo "========================================================================== echo "Creating stub headers" HEADERS_DIR="$GITHUB_WORKSPACE/ci/headers" -XRSDK_HEADERS_DIR="$HEADERS_DIR/xr-voice-sdk" mkdir -p "${HEADERS_DIR}" mkdir -p "${HEADERS_DIR}/rdk/iarmbus" mkdir -p "${HEADERS_DIR}/rdk/ds" mkdir -p "${HEADERS_DIR}/rdk/iarmmgrs-hal" -mkdir -p "${XRSDK_HEADERS_DIR}" - -# Copy real xr-voice-sdk headers. -# xr_fdc.h is NOT copied: only needed when FDC_ENABLED=ON -cp "$GITHUB_WORKSPACE/xr-voice-sdk/src/xr-speech-vrex/xrsv.h" "${XRSDK_HEADERS_DIR}/" -cp "$GITHUB_WORKSPACE/xr-voice-sdk/src/xr-speech-router/xrsr.h" "${XRSDK_HEADERS_DIR}/" -cp "$GITHUB_WORKSPACE/xr-voice-sdk/src/xr-mq/xr_mq.h" "${XRSDK_HEADERS_DIR}/" -cp "$GITHUB_WORKSPACE/xr-voice-sdk/src/xr-speech-vrex/xrsv_http/xrsv_http.h" "${XRSDK_HEADERS_DIR}/" -cp "$GITHUB_WORKSPACE/xr-voice-sdk/src/xr-speech-vrex/xrsv_ws_nextgen/xrsv_ws_nextgen.h" "${XRSDK_HEADERS_DIR}/" -cp "$GITHUB_WORKSPACE/xr-voice-sdk/src/xr-timestamp/xr_timestamp.h" "${XRSDK_HEADERS_DIR}/" - -# Generate rdkx_logger_modules.h from xr-voice-sdk's module configuration, -# then copy the real rdkx_logger and xr_voice_sdk headers. -# This replaces the hand-written ci/mocks/control/ stubs. -python3 "$GITHUB_WORKSPACE/xr-voice-sdk/scripts/rdkx_logger_modules_to_c.py" \ - "$GITHUB_WORKSPACE/xr-voice-sdk/src/xr-logger/rdkv/rdkx_logger_modules.json" \ - "${XRSDK_HEADERS_DIR}/rdkx_logger_modules" "mw" -cp "$GITHUB_WORKSPACE/xr-voice-sdk/src/xr-logger/rdkx_logger_mw.h" "${XRSDK_HEADERS_DIR}/rdkx_logger.h" -cp "$GITHUB_WORKSPACE/xr-voice-sdk/src/xr_voice_sdk.h" "${XRSDK_HEADERS_DIR}/xr_voice_sdk.h" + +# Use the Yocto safec_lib.h sysroot header for CI builds without libsafec. +# Add include guards because the upstream header does not provide them. +cp "$SAFEC_WRAPPER_DIR/safec_lib.h" "$HEADERS_DIR/safec_lib.h" +sed -i '1s/^/#ifndef CTRLM_CI_SAFEC_LIB_H\n#define CTRLM_CI_SAFEC_LIB_H\n/' "$HEADERS_DIR/safec_lib.h" +printf '\n#endif /* CTRLM_CI_SAFEC_LIB_H */\n' >> "$HEADERS_DIR/safec_lib.h" +# patching parseFormat to avoid -Wmaybe-uninitialized warnings in ctrlm_database.cpp from the safec wrapper's dummy implementation +sed -i 's/static inline int parseFormat(const char \*dst,/static inline int parseFormat(char *dst,/' "$HEADERS_DIR/safec_lib.h" +# patching strcpy_s to avoid Coverity's array-vs-NULL warning on string literals while +# preserving the dummy wrapper's null and bounds checks in CI builds. +perl -0pi -e 's{#define strcpy_s\(dst,max,src\) \(src != NULL\)\?\(\(max > strlen\(src\)\)\?EOK:ESLEMAX\):ESNULLP; \\\n if\(\(src != NULL\) && \(max > strlen\(src\)\)\) strcpy\(dst,src\);}{#define strcpy_s(dst,max,src) ({ const char *ctrlm_ci_src__ = (src); ctrlm_ci_src__ != NULL ? (((max) > strlen(ctrlm_ci_src__)) ? (strcpy((dst), ctrlm_ci_src__), EOK) : ESLEMAX) : ESNULLP; })}s or die "failed to patch strcpy_s in safec_lib.h\n"' "$HEADERS_DIR/safec_lib.h" +# patching strncpy_s to avoid the wrapper's raw strncpy expansion, which triggers +# -Wstringop-truncation in CI even though ctrlm manually terminates the destination buffer. +perl -0pi -e 's{#define strncpy_s\(dst,max,src,len\) \(src != NULL\)\?\(\(len <= max\)\?EOK:ESLEMAX\):ESNULLP; \\\n if\(\(src != NULL\) && \(len <= max\)\) strncpy\(dst,src,len\);}{#define strncpy_s(dst,max,src,len) (src != NULL)?((len <= max)?EOK:ESLEMAX):ESNULLP; \\\n if((src != NULL) && (len <= max)) { size_t copy_len = strnlen(src, len); memcpy(dst, src, copy_len); if(copy_len < (size_t)(max)) memset((char *)(dst) + copy_len, 0, (size_t)(max) - copy_len); }}s or die "failed to patch strncpy_s in safec_lib.h\n"' "$HEADERS_DIR/safec_lib.h" + +# Stage rdkversion.h before building xr-voice-sdk. +cp "$RDKVERSION_DIR/src/rdkversion.h" "$HEADERS_DIR/rdkversion.h" + +# Build xr-voice-sdk and install its headers under ${HEADERS_DIR}/xr-voice-sdk/. +# Version doesn't matter here, but we try to get the latest tag for good measure since it's included in the generated headers and may be used by downstream code. +XRSDK_REF=$(git ls-remote --tags https://github.com/rdkcentral/xr-voice-sdk.git \ + | grep -oP '\d+\.\d+\.\d+$' | sort -V | tail -1) +echo "Building xr-voice-sdk at ref ${XRSDK_REF}" +cmake -G Ninja \ + -S "$GITHUB_WORKSPACE/xr-voice-sdk" \ + -B "$GITHUB_WORKSPACE/build/xr-voice-sdk" \ + -DCMAKE_INSTALL_PREFIX="${HEADERS_DIR}" \ + -DCMAKE_INSTALL_INCLUDEDIR="xr-voice-sdk" \ + -DCMAKE_INSTALL_SYSCONFDIR="${HEADERS_DIR}/etc" \ + -DCMAKE_C_FLAGS="-I${HEADERS_DIR} -DSAFEC_DUMMY_API" \ + -DSTAGING_BINDIR_NATIVE="/usr/bin" \ + -DCMAKE_PROJECT_VERSION="${XRSDK_REF}" \ + -DVAD_ENABLED=OFF \ + -DINSTALL_INTERNAL_HEADERS=ON + +cmake --build "$GITHUB_WORKSPACE/build/xr-voice-sdk" +cmake --install "$GITHUB_WORKSPACE/build/xr-voice-sdk" --component headers +cmake --install "$GITHUB_WORKSPACE/build/xr-voice-sdk" --component internal-headers cd "${HEADERS_DIR}" @@ -160,16 +179,11 @@ find "$IARMMGRS_DIR" -name comcastIrKeyCodes.h -print -quit | xargs -r -I{} cp " [ -f comcastIrKeyCodes.h ] # rdkversion.h (used by ctrlm_main.cpp) -cp "$RDKVERSION_DIR/src/rdkversion.h" rdkversion.h [ -f rdkversion.h ] # secure_wrapper (types provided via empty stub — no v_secure_* calls in core) touch secure_wrapper.h -# safec compatibility header - committed in ci/mocks, copied here so it is -# resolved on the generated-headers include path. -cp "$GITHUB_WORKSPACE/ci/mocks/safec_lib.h" safec_lib.h - echo "Stub headers created successfully" cd "${GITHUB_WORKSPACE}" @@ -190,13 +204,15 @@ cat > /tmp/stub.c << 'STUB_EOF' void __stub_placeholder(void) {} STUB_EOF -# Build stub .so for each missing library -# nopoll and dshalcli are unused (factory-only) but unconditionally linked by CMakeLists.txt -# We can remove them from the link list in the future if desired, but for now just provide stubs to satisfy the linker. -for lib in xr-voice-sdk rdkversion IARMBus ds nopoll dshalcli rfcapi secure_wrapper evdev; do +# Build stub .so files for libraries still linked in CI. +# nopoll and dshalcli are factory-only but still linked unconditionally. +for lib in rdkversion IARMBus ds nopoll dshalcli rfcapi secure_wrapper evdev; do gcc -shared -fPIC -o "${STUB_LIB_DIR}/lib${lib}.so" /tmp/stub.c done +# Copy the real xr-voice-sdk .so alongside the stubs. +cp "$GITHUB_WORKSPACE/build/xr-voice-sdk/src/libxr-voice-sdk.so" "${STUB_LIB_DIR}/libxr-voice-sdk.so" + rm /tmp/stub.c echo "Stub libraries created in ${STUB_LIB_DIR}" diff --git a/ci/cov_build.sh b/ci/cov_build.sh index 3a51b921..e3181ddc 100644 --- a/ci/cov_build.sh +++ b/ci/cov_build.sh @@ -28,9 +28,7 @@ ls -la "${GITHUB_WORKSPACE}" echo "building control (ctrlm-main)" XRSDK_REAL_HEADERS="$GITHUB_WORKSPACE/ci/headers/xr-voice-sdk" -XLOG_COMPAT="$GITHUB_WORKSPACE/ci/mocks/xlog_ci_compat.h" MOCK_DIR="$GITHUB_WORKSPACE/entservices-testframework/Tests/mocks" -MOCK_OVERRIDES="$GITHUB_WORKSPACE/ci/mocks/testframework_overrides.h" HEADERS_DIR="$GITHUB_WORKSPACE/ci/headers" EMPTY_JSON="$GITHUB_WORKSPACE/install/usr/include/ctrlm_config_empty.json" GLIB_CFLAGS="$(pkg-config --cflags glib-2.0)" @@ -77,9 +75,7 @@ cmake -G Ninja -S "$GITHUB_WORKSPACE" -B build/control \ -I ${GITHUB_WORKSPACE}/install/usr/include \ -I /usr/include/libdrm \ ${GLIB_CFLAGS} \ --include ${XLOG_COMPAT} \ -include ${MOCK_DIR}/Iarm.h \ --include ${MOCK_OVERRIDES} \ -include ${MOCK_DIR}/devicesettings.h \ -include ${MOCK_DIR}/Rfc.h \ -Wall -Wno-error \ diff --git a/ci/mocks/devicesettings_ctrlm.patch b/ci/mocks/devicesettings_ctrlm.patch deleted file mode 100644 index d2faf8a8..00000000 --- a/ci/mocks/devicesettings_ctrlm.patch +++ /dev/null @@ -1,40 +0,0 @@ ---- a/Tests/mocks/devicesettings.h 2026-04-21 19:12:58.154981897 +0000 -+++ b/Tests/mocks/devicesettings.h 2026-04-21 19:13:50.591192520 +0000 -@@ -72,6 +72,16 @@ - dsAUDIOPORT_TYPE_MAX /**< Maximum index for audio port type. */ - } dsAudioPortType_t; - -+typedef enum _dsAudioDuckingAction_t { -+ dsAUDIO_DUCKINGACTION_START = 0, -+ dsAUDIO_DUCKINGACTION_STOP = 1 -+} dsAudioDuckingAction_t; -+ -+typedef enum _dsAudioDuckingType_t { -+ dsAUDIO_DUCKINGTYPE_ABSOLUTE = 0, -+ dsAUDIO_DUCKINGTYPE_RELATIVE = 1 -+} dsAudioDuckingType_t; -+ - typedef enum _dsVideoPortType_t { - dsVIDEOPORT_TYPE_RF = 0, ///< RF modulator (channel 3/4) video output - dsVIDEOPORT_TYPE_BB, ///< Baseband (composite, RCA) video output -@@ -934,6 +944,11 @@ - void enableARC(dsAudioARCTypes_t type, bool enable); - uint32_t getDolbyVolumeMode() const; - void setStereoMode(const std::string &mode, bool persist); -+ void setAudioDucking(dsAudioDuckingAction_t action, dsAudioDuckingType_t type, float level) { -+ (void)action; -+ (void)type; -+ (void)level; -+ } - - - -@@ -1420,6 +1435,8 @@ - static ManagerImpl* impl; - - public: -+ static bool IsInitialized; -+ - Manager(); - - static void setImpl(ManagerImpl* newImpl); diff --git a/ci/mocks/safec_lib.h b/ci/mocks/safec_lib.h deleted file mode 100644 index 37d75748..00000000 --- a/ci/mocks/safec_lib.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * If not stated otherwise in this file or this component's license file the - * following copyright and licenses apply: - * - * Copyright 2026 RDK Management - * - * 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. - */ - -/* - * Compatibility header: maps ctrlm's local include name to the real libsafec - * package headers (libsafec-dev / safec-common-wrapper in production). - * - * In CI this file is copied from ci/mocks/ into ci/headers/ by - * build_dependencies.sh so it is resolved on the generated-headers include - * path used by cov_build.sh. - * - * This exists because ctrlm includes safec_lib.h directly, while the native CI - * environment provides the underlying libsafec package headers instead of that - * project-local wrapper. - */ - -#ifndef CTRLM_CI_SAFEC_LIB_H_ -#define CTRLM_CI_SAFEC_LIB_H_ - -#include -#include -#include - -#ifndef ERR_CHK -#define ERR_CHK(rc) do { (void)(rc); } while(0) -#endif - -#endif /* CTRLM_CI_SAFEC_LIB_H_ */ diff --git a/ci/mocks/testframework_overrides.h b/ci/mocks/testframework_overrides.h deleted file mode 100644 index 22b8a0a2..00000000 --- a/ci/mocks/testframework_overrides.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * If not stated otherwise in this file or this component's license file the - * following copyright and licenses apply: - * - * Copyright 2026 RDK Management - * - * 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. - */ -/* - * CI patch layer for gaps in the entservices-testframework mock headers. - * - * ctrlm needs a few IARM declarations that are missing from the testframework - * headers used by this reduced build. This file adds only those missing pieces - * and can be removed once they exist upstream. - */ -#ifndef CTRLM_CI_TESTFRAMEWORK_OVERRIDES_H_ -#define CTRLM_CI_TESTFRAMEWORK_OVERRIDES_H_ - -/* Pinned testframework Iarm.h stops at UNKNOWN; ctrlm also references MAX. */ -#ifndef DEEPSLEEP_WAKEUPREASON_MAX -#define DEEPSLEEP_WAKEUPREASON_MAX (DEEPSLEEP_WAKEUPREASON_UNKNOWN + 1) -#endif - -/* IARM common API string not present in the pinned testframework mock */ -#ifndef IARM_BUS_COMMON_API_PowerPreChange -#define IARM_BUS_COMMON_API_PowerPreChange "PowerPreChange" -#endif - -/* Struct not present in the pinned testframework mock */ -#ifndef CTRLM_IARM_BUS_COMMON_API_POWERPRECHANGE_PARAM_T_DEFINED -#define CTRLM_IARM_BUS_COMMON_API_POWERPRECHANGE_PARAM_T_DEFINED -typedef struct { - IARM_Bus_PWRMgr_PowerState_t newState; - IARM_Bus_PWRMgr_PowerState_t curState; -} IARM_Bus_CommonAPI_PowerPreChange_Param_t; -#endif - -#endif /* CTRLM_CI_TESTFRAMEWORK_OVERRIDES_H_ */ diff --git a/ci/mocks/xlog_ci_compat.h b/ci/mocks/xlog_ci_compat.h deleted file mode 100644 index 43836b73..00000000 --- a/ci/mocks/xlog_ci_compat.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * If not stated otherwise in this file or this component's license file the - * following copyright and licenses apply: - * - * Copyright 2026 RDK Management - * - * 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. - */ - -/* - * CI compatibility shim. - * - * The production rdkx_logger.h is included transitively everywhere via - * ctrlm_log.h. In the Yocto build the SDK headers pull several std:: names - * into the global namespace. A handful of ctrlm TUs (e.g. ctrlm_utils.cpp) - * rely on those names being globally visible. This tiny header replicates - * that behaviour for the CI native build. - */ -#ifndef CTRLM_CI_XLOG_COMPAT_H_ -#define CTRLM_CI_XLOG_COMPAT_H_ - -#ifdef __cplusplus -#include -#include -#include -using std::get; -using std::map; -using std::string; -using std::tuple; -#endif - -#endif /* CTRLM_CI_XLOG_COMPAT_H_ */ diff --git a/src/ctrlm_utils.cpp b/src/ctrlm_utils.cpp index b77595ac..40f355ed 100644 --- a/src/ctrlm_utils.cpp +++ b/src/ctrlm_utils.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include "ctrlm.h" #include "ctrlm_utils.h" #include @@ -47,6 +48,11 @@ #include // end dsMgr includes +using std::get; +using std::map; +using std::string; +using std::tuple; + #define BLOCK_SIZE (1024 * 4 * 10) /* bytes */ #define MAX_RECURSE_DEPTH 20 diff --git a/src/voice/ctrlm_voice_obj.cpp b/src/voice/ctrlm_voice_obj.cpp index a6787b1e..af6b1731 100644 --- a/src/voice/ctrlm_voice_obj.cpp +++ b/src/voice/ctrlm_voice_obj.cpp @@ -2921,11 +2921,15 @@ void ctrlm_voice_t::voice_stream_end_callback(ctrlm_voice_stream_end_cb_t *strea if(session->packets_processed > 0) { uint32_t stream_duration = session->packets_processed * 20; // assume 20 ms per packet + #ifdef TELEMETRY_SUPPORT uint32_t samples_per_packet = 320; // 16 kHz samples at 20 ms per packet + #endif if(session->format.type == CTRLM_VOICE_FORMAT_ADPCM_FRAME) { uint32_t frame_duration_us = (session->format.value.adpcm_frame.size_packet - session->format.value.adpcm_frame.size_header) * 125; // 125 us per byte for ADPCM at 16 kHz stream_duration = (session->packets_processed * frame_duration_us) / 1000; + #ifdef TELEMETRY_SUPPORT samples_per_packet = (session->format.value.adpcm_frame.size_packet - session->format.value.adpcm_frame.size_header) * 2; // 2 samples per byte for ADPCM + #endif } XLOGD_AUTOMATION_TELEMETRY("src <%s> Packets Lost/Total <%u/%u> %.02f%% duration <%u> ms", ctrlm_voice_device_str(session->voice_device), session->packets_lost, session->packets_lost + session->packets_processed, 100.0 * ((double)session->packets_lost / (double)(session->packets_lost + session->packets_processed)), stream_duration); #ifdef TELEMETRY_SUPPORT