RDKEMW-17086: Enable or Disable MS12 cont audio output mode. - #262
RDKEMW-17086: Enable or Disable MS12 cont audio output mode.#262shashank4388 wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds a new “application audio configuration” control path (intended for MS12 continuous audio output mode and similar per-application behaviors) by introducing new IARM RPC calls (client/server), RPC parameter structs, and new Host APIs to set/get/list supported configurations.
Changes:
- Added IARM bus API identifiers and RPC parameter structs for application audio configuration set/get/list.
- Implemented RPC server handlers in
rpc/srv/dsAudio.cthat dynamically resolve HAL entry points and service the new RPC calls. - Added RPC client wrappers in
rpc/cli/dsAudio.cand exposed higher-levelHostmethods inds/host.cpp/ds/include/host.hpp.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 13 comments.
Show a summary per file
| File | Description |
|---|---|
| rpc/srv/dsAudio.c | Registers new IARM calls and adds server-side handlers for set/get/list; current implementation has critical NULL-deref/stack-overwrite issues and a misleading error message. |
| rpc/include/dsRpc.h | Adds new IARM API string constants and RPC parameter structs for application audio configuration APIs. |
| rpc/cli/dsAudio.c | Adds client-side wrappers for set/get/list; current implementation has format-string bugs, missing validation, and doesn’t propagate server error codes. |
| ds/include/host.hpp | Exposes new Host APIs; currently declares an unimplemented const char* overload. |
| ds/host.cpp | Implements Host wrappers and adds documentation; contains incorrect @see reference and misleading/unprofessional log messages. |
| ds/audioOutputPort.cpp | Removes an extraneous blank line. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| dsApplicationAudioConfigListParam_t *param = (dsApplicationAudioConfigListParam_t *)arg; | ||
| dsApplicationAudioConfigList_t configList; | ||
| memset(&configList, 0, sizeof(dsApplicationAudioConfigListParam_t)); | ||
| configList.size = param->appAudioConfigList.size; | ||
| if (func != 0 && param != NULL) | ||
| { |
| if (ret != dsERR_NONE) | ||
| { | ||
| param->result = ret; | ||
| INT_ERROR("%s: (SERVER) Unable to set Application audio configuration\n", __FUNCTION__); |
| dsApplicationAudioConfigParam_t *param = (dsApplicationAudioConfigParam_t *)arg; | ||
| dsApplicationAudioConfig_t config; | ||
| memset(config.configName, 0, sizeof(dsApplicationAudioConfig_t)); | ||
| strncpy(config.configName, param->audioConfig.configName, sizeof(dsApplicationAudioConfig_t)); | ||
| if (func != 0 && param != NULL) | ||
| { |
| dsApplicationAudioConfigParam_t *param = (dsApplicationAudioConfigParam_t *)arg; | ||
| memset(config.configName, 0, sizeof(dsApplicationAudioConfig_t)); | ||
| strncpy(config.configName, param->audioConfig.configName, sizeof(dsApplicationAudioConfig_t)); | ||
| if (func != 0 && param != NULL) | ||
| { |
| dsError_t dsSetApplicationAudioConfig(intptr_t handle, dsApplicationAudioConfig_t* audioConfig, bool enable) | ||
| { | ||
| _DEBUG_ENTER(); | ||
| INT_ERROR("Shashank...... dscli dsSetApplicationAudioConfig %s\n", audioConfig); | ||
| dsApplicationAudioConfigParam_t param; | ||
| param.handle = handle; | ||
| param.enable = enable; | ||
| IARM_Result_t rpcRet = IARM_RESULT_SUCCESS; | ||
| memset(param.audioConfig.configName, '\0', sizeof(param.audioConfig)); | ||
| strncpy(param.audioConfig.configName, audioConfig->configName, (DS_MAX_APPLICATION_AUDIO_CONFIG_NAME_LEN -1)); | ||
| rpcRet = IARM_Bus_Call(IARM_BUS_DSMGR_NAME, | ||
| (char *)IARM_BUS_DSMGR_API_dsSetApplicationAudioConfig, | ||
| (void *)¶m, | ||
| sizeof(param)); | ||
|
|
||
| if (IARM_RESULT_SUCCESS == rpcRet) | ||
| { | ||
| INT_ERROR("Shashank... Exiting dsSetApplicationAudioConfig Error None"); | ||
| return dsERR_NONE; | ||
| } | ||
| INT_ERROR("Shashank2... Exiting dsSetApplicationAudioConfig"); | ||
| return dsERR_GENERAL ; | ||
| } |
| std::cout << "Failed to set AudioOutputPort::setApplicationAudioConfig\n"; | ||
| throw Exception(ret); | ||
| } | ||
| INT_INFO("Exiting AudioOutputPort::setApplicationAudioConfig\n"); |
| std::cout << "Failed to set AudioOutputPort::getApplicationAudioConfig\n"; | ||
| throw Exception(ret); | ||
| } | ||
| INT_INFO("Exiting AudioOutputPort::getApplicationAudioConfig\n"); |
| for (int count =0; count < appAudioConfigList.returnedCount; count++) { | ||
| configList.push_back(appAudioConfigList.config[count].configName); | ||
| } | ||
| INT_INFO("Exiting AudioOutputPort::getApplicationAudioConfigList\n"); |
| dsError_t dsGetApplicationAudioConfigList(intptr_t handle, dsApplicationAudioConfigList_t* appAudioConfigList) | ||
| { | ||
| IARM_Result_t rpcRet = IARM_RESULT_SUCCESS; | ||
| dsApplicationAudioConfigListParam_t param; | ||
|
|
||
| param.handle = handle; | ||
| memset(¶m.appAudioConfigList, 0, sizeof(dsApplicationAudioConfigList_t)); | ||
| param.appAudioConfigList.size = sizeof(dsApplicationAudioConfigList_t); | ||
|
|
| if (IARM_RESULT_SUCCESS != rpcRet) | ||
| { | ||
| printf("%s: (GET) GENERAL ERROR\n", __FUNCTION__); | ||
| return dsERR_GENERAL; | ||
| } | ||
|
|
||
| appAudioConfigList->size = param.appAudioConfigList.size; | ||
| appAudioConfigList->returnedCount = param.appAudioConfigList.returnedCount; | ||
| appAudioConfigList->totalCount = param.appAudioConfigList.totalCount; | ||
| for (int count=0; count < param.appAudioConfigList.returnedCount; count++) { | ||
| strncpy(appAudioConfigList->config[count].configName, param.appAudioConfigList.config[count].configName, | ||
| (DS_MAX_APPLICATION_AUDIO_CONFIG_NAME_LEN -1) ); | ||
| } | ||
| return dsERR_NONE; |
d741ec3 to
eb778ec
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.
Comments suppressed due to low confidence (2)
rpc/cli/dsAudio.c:468
- enable is dereferenced without a NULL check ("*enable = param.enable"). This can crash callers passing a null enable pointer.
if (audioConfig == NULL) {
INT_ERROR("%s:Invalid parameter", __func__);
return dsERR_GENERAL;
}
ds/include/host.hpp:426
- Host declares setApplicationAudioConfig(const char*, bool) but there is no definition in this PR. Because it is a better match than the std::string overload for string literals, this can easily lead to link errors. Either remove it or provide an inline forwarding wrapper.
void setAudioAtmosOutputMode(bool enable);
void setApplicationAudioConfig(const char* audioConfig, bool enable);
void setAssociatedAudioMixing(const bool mixing);
| if (func != 0 && param != NULL) | ||
| { | ||
| strncpy(config.configName, param->audioConfig.configName, sizeof(dsApplicationAudioConfig_t)); | ||
| ret = func(param->handle, &config, param->enable); |
| if (func != 0 && param != NULL) | ||
| { | ||
| strncpy(config.configName, param->audioConfig.configName, sizeof(dsApplicationAudioConfig_t)); | ||
| ret = func(param->handle, &config, &enable); | ||
| if (ret != dsERR_NONE) |
| IARM_Result_t rpcRet = IARM_RESULT_SUCCESS; | ||
| memset(param.audioConfig.configName, '\0', sizeof(param.audioConfig)); | ||
| strncpy(param.audioConfig.configName, audioConfig->configName, (DS_MAX_APPLICATION_AUDIO_CONFIG_NAME_LEN -1)); |
| IARM_Result_t rpcRet = IARM_RESULT_SUCCESS; | ||
| memset(param.audioConfig.configName, '\0', sizeof(param.audioConfig)); | ||
| strncpy(param.audioConfig.configName, audioConfig->configName, (DS_MAX_APPLICATION_AUDIO_CONFIG_NAME_LEN -1)); |
| typedef dsError_t (*dsGetApplicationAudioConfigList_t)(intptr_t handle, dsApplicationAudioConfigList_t* audioConfigList); | ||
| static dsGetApplicationAudioConfigList_t func = 0; | ||
| INT_ERROR("Inside _dsGetApplicationAudioConfigList_t srv\n"); | ||
| if (func == 0) { |
eb778ec to
82e8a5d
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 6 comments.
Comments suppressed due to low confidence (5)
rpc/cli/dsAudio.c:412
memset(param.audioConfig, ...)passes a struct value where a pointer is required, which will not compile (and is redundant sinceparamis already zeroed). Use¶m.audioConfig(or remove the line entirely).
memset(param.audioConfig, '\0', sizeof(param.audioConfig));
rpc/cli/dsAudio.c:476
memset(param.audioConfig, ...)passes a struct value where a pointer is required, which will not compile (and is redundant sinceparamis already zeroed). Use¶m.audioConfig(or remove the line entirely).
memset(param.audioConfig, 0, sizeof(param.audioConfig));
rpc/cli/dsAudio.c:434
- On invalid input, this should return
dsERR_INVALID_PARAM(consistent with other APIs in this file) rather thandsERR_GENERAL. Also add a newline so the log doesn’t run into subsequent output.
if (appAudioConfigList == NULL) {
INT_ERROR("%s:Invalid parameter", __func__);
return dsERR_GENERAL;
}
rpc/cli/dsAudio.c:468
enableis dereferenced on success but is never validated. This can segfault if the caller passes NULL. Also returndsERR_INVALID_PARAMfor invalid input to match other APIs in this file.
if (audioConfig == NULL) {
INT_ERROR("%s:Invalid parameter", __func__);
return dsERR_GENERAL;
}
ds/include/host.hpp:425
setApplicationAudioConfig(const char*, ...)is declared but has no definition in this PR, which can lead to undefined-symbol link errors if used. Consider making it an inline forwarder to thestd::stringoverload (or remove the duplicate overload).
void setApplicationAudioConfig(const char* audioConfig, bool enable);
| if (audioConfig == NULL) { | ||
| INT_ERROR("%s:Invalid parameter", __func__); | ||
| return dsERR_GENERAL; | ||
| } |
| strncpy(config.configName, audioConfig.c_str(), (DS_MAX_APPLICATION_AUDIO_CONFIG_NAME_LEN - 1)); | ||
| dsError_t ret = dsSetApplicationAudioConfig (NULL, &config, enable); | ||
| if (ret != dsERR_NONE) { | ||
| std::cout << "Failed to set Host::setApplicationAudioConfig\n"; |
| { | ||
| INT_INFO("Shashank............Calling getApplicationAudioConfig\n"); | ||
| dsApplicationAudioConfig_t config; |
| strncpy(config.configName, audioConfig.c_str(), (DS_MAX_APPLICATION_AUDIO_CONFIG_NAME_LEN -1 )); | ||
| dsError_t ret = dsGetApplicationAudioConfig (NULL, &config, enable); | ||
| if (ret != dsERR_NONE) { | ||
| std::cout << "Failed to set Host::getApplicationAudioConfig\n"; |
| { | ||
| INT_INFO("Shashank............Calling getApplicationAudioConfigList\n"); | ||
| dsApplicationAudioConfigList_t appAudioConfigList; |
| memset(&appAudioConfigList, 0, sizeof(dsApplicationAudioConfigList_t)); | ||
| dsError_t ret = dsGetApplicationAudioConfigList(NULL, &appAudioConfigList); | ||
| if (ret != dsERR_NONE) { | ||
| std::cout << "Failed to set Host::getApplicationAudioConfigList\n"; |
82e8a5d to
bf88a7d
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.
Comments suppressed due to low confidence (7)
ds/include/host.hpp:425
- Host declares setApplicationAudioConfig(const char*) but there is no implementation in this PR (only the std::string overload is implemented). This leaves a public API with an unresolved symbol if called; either remove it or provide a small forwarding wrapper.
void setApplicationAudioConfig(const char* audioConfig, bool enable);
ds/host.cpp:606
- This error log says "Failed to set" but the method is a getter, which makes troubleshooting confusing.
INT_ERROR("Failed to set Host::getApplicationAudioConfigList\n");
rpc/cli/dsAudio.c:410
- This client API currently drops the server-side dsError_t and always returns dsERR_GENERAL on failure, and it includes personal-name debug logs. Returning the actual param.result aligns with existing dsAudio RPC client patterns and preserves error details.
INT_ERROR("Shashank...... dscli dsSetApplicationAudioConfig %s\n", audioConfig->configName);
dsApplicationAudioConfigParam_t param;
memset(¶m, 0, sizeof(param));
param.handle = handle;
param.enable = enable;
rpc/cli/dsAudio.c:473
- This client API currently drops the server-side dsError_t and always returns dsERR_GENERAL on failure, and it includes personal-name debug logs. Return param.result (after a successful IARM call) to preserve the actual error and match other client functions in this file.
INT_ERROR("Shashank...... dscli dsGetApplicationAudioConfig %s\n", audioConfig->configName);
dsApplicationAudioConfigParam_t param;
memset(¶m, 0, sizeof(param));
param.handle = handle;
// By default enable will be false.
rpc/cli/dsAudio.c:450
- Error handling and copying in dsGetApplicationAudioConfigList should avoid printf, preserve the server-side dsError_t (param.result), and ensure copied configName strings are NUL-terminated.
if (IARM_RESULT_SUCCESS != rpcRet || param.result != dsERR_NONE)
{
printf("%s: (GET) GENERAL ERROR\n", __FUNCTION__);
return dsERR_GENERAL;
}
rpc/srv/dsAudio.c:3713
- These are normal control-flow logs (function entry / symbol resolved) but are emitted as INT_ERROR, which is misleading and noisy. Nearby RPC wrappers use INT_DEBUG/INT_INFO for the same cases (e.g., rpc/srv/dsAudio.c:4368-4372).
INT_ERROR("Inside _dsGetApplicationAudioConfigList_t srv\n");
if (func == 0) {
void *dllib = dlopen(RDK_DSHAL_NAME, RTLD_LAZY);
if (dllib) {
func = (dsGetApplicationAudioConfigList_t) dlsym(dllib, "dsGetApplicationAudioConfigList");
rpc/srv/dsAudio.c:3753
- This is a normal control-flow log but is emitted as INT_ERROR, which is misleading and noisy. Prefer INT_DEBUG (or remove) for function-exit tracing.
INT_ERROR("Inside _dsGetApplicationAudioConfigList srv\n");
| INT_ERROR("Inside _dsSetApplicationAudioConfig srv\n"); | ||
| if (func == 0) { | ||
| void *dllib = dlopen(RDK_DSHAL_NAME, RTLD_LAZY); | ||
| if (dllib) { | ||
| func = (dsSetApplicationAudioConfig_t) dlsym(dllib, "dsSetApplicationAudioConfig"); | ||
| if (func) { | ||
| INT_ERROR("dsSetApplicationAudioConfig_t(int, bool) is defined and loaded\r\n"); | ||
| } | ||
| else { | ||
| INT_ERROR("dsSetApplicationAudioConfig_t(int, bool) is not defined\r\n"); | ||
| } |
| result = IARM_RESULT_SUCCESS; | ||
| } | ||
| } | ||
| INT_ERROR("Inside _dsSetApplicationAudioConfig srv\n"); |
| INT_ERROR("Inside _dsGetApplicationAudioConfig srv\n"); | ||
| if (func == 0) { | ||
| void *dllib = dlopen(RDK_DSHAL_NAME, RTLD_LAZY); | ||
| if (dllib) { | ||
| func = (dsGetApplicationAudioConfig_t) dlsym(dllib, "dsGetApplicationAudioConfig"); | ||
| if (func) { | ||
| INT_ERROR("dsGetApplicationAudioConfig_t(int, bool) is defined and loaded\r\n"); | ||
| } | ||
| else { | ||
| INT_ERROR("dsGetApplicationAudioConfig_t(int, bool) is not defined\r\n"); | ||
| } |
| result = IARM_RESULT_SUCCESS; | ||
| } | ||
| } | ||
| INT_ERROR("Inside _dsGetApplicationAudioConfig srv\n"); |
bf88a7d to
d1ed81f
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (5)
rpc/cli/dsAudio.c:410
- The new client RPC wrapper logs personal/debug strings at error level and drops the underlying
dsError_ton failure (it always returnsdsERR_GENERALunless fully successful). This makes troubleshooting harder and can spam error logs on normal paths; prefer neutral logs and returnparam.resultwhen the bus call succeeded.
INT_ERROR("Shashank...... dscli dsSetApplicationAudioConfig %s\n", audioConfig->configName);
dsApplicationAudioConfigParam_t param;
memset(¶m, 0, sizeof(param));
param.handle = handle;
param.enable = enable;
rpc/cli/dsAudio.c:450
- On error, this wrapper always returns
dsERR_GENERALand logs a generic message. If the RPC call itself succeeded but the server/HAL returned a specificdsError_t, that information should be propagated back to the caller.
if (IARM_RESULT_SUCCESS != rpcRet || param.result != dsERR_NONE)
{
printf("%s: (GET) GENERAL ERROR\n", __FUNCTION__);
return dsERR_GENERAL;
}
rpc/cli/dsAudio.c:458
strncpyhere does not guarantee NUL-termination, and the destination buffer is not cleared first. If the source name is exactlyDS_MAX_APPLICATION_AUDIO_CONFIG_NAME_LEN-1bytes,configNamemay become unterminated and later string operations can read past the buffer.
for (int count=0; count < param.appAudioConfigList.returnedCount; count++) {
strncpy(appAudioConfigList->config[count].configName, param.appAudioConfigList.config[count].configName,
(DS_MAX_APPLICATION_AUDIO_CONFIG_NAME_LEN -1) );
}
rpc/cli/dsAudio.c:473
- This new client RPC wrapper logs personal/debug strings at error level and drops the underlying
dsError_ton failure (it always returnsdsERR_GENERALunless fully successful). Prefer neutral logs and returnparam.resultwhen the RPC call succeeded so callers can react appropriately.
INT_ERROR("Shashank...... dscli dsGetApplicationAudioConfig %s\n", audioConfig->configName);
dsApplicationAudioConfigParam_t param;
memset(¶m, 0, sizeof(param));
param.handle = handle;
// By default enable will be false.
ds/host.cpp:611
- This method appends to the caller-provided vector without clearing it first. Repeated calls will accumulate duplicates, which is inconsistent with existing list-style APIs in this file (e.g.,
Host::getHostEDIDclears its output vector before filling).
for (int count =0; count < appAudioConfigList.returnedCount; count++) {
configList.push_back(appAudioConfigList.config[count].configName);
}
| func = (dsGetApplicationAudioConfigList_t) dlsym(dllib, "dsGetApplicationAudioConfigList"); | ||
| if (func) { | ||
| INT_ERROR("dsGetApplicationAudioConfigList_t is defined and loaded\r\n"); | ||
| } | ||
| else { | ||
| INT_ERROR("dsGetApplicationAudioConfigList is not defined\r\n"); | ||
| } | ||
| dlclose(dllib); |
| func = (dsSetApplicationAudioConfig_t) dlsym(dllib, "dsSetApplicationAudioConfig"); | ||
| if (func) { | ||
| INT_ERROR("dsSetApplicationAudioConfig_t(int, bool) is defined and loaded\r\n"); | ||
| } | ||
| else { | ||
| INT_ERROR("dsSetApplicationAudioConfig_t(int, bool) is not defined\r\n"); | ||
| } | ||
| dlclose(dllib); |
| func = (dsGetApplicationAudioConfig_t) dlsym(dllib, "dsGetApplicationAudioConfig"); | ||
| if (func) { | ||
| INT_ERROR("dsGetApplicationAudioConfig_t(int, bool) is defined and loaded\r\n"); | ||
| } | ||
| else { | ||
| INT_ERROR("dsGetApplicationAudioConfig_t(int, bool) is not defined\r\n"); | ||
| } | ||
| dlclose(dllib); |
https://ccp.sys.comcast.net/browse/RDKEMW-17086