共 11 个文件变更+687-75
@@ -33,6 +33,7 @@
33 "accessibility",33 "accessibility",
34 "audio_framework",34 "audio_framework",
35 "av_codec",35 "av_codec",
36+ "config_policy",
36 "cJSON",37 "cJSON",
37 "c_utils",38 "c_utils",
38 "device_security_level",39 "device_security_level",
@@ -0,0 +1,46 @@
1+/*
2+ * Copyright (c) 2024-2025 Huawei Device Co., Ltd.
3+ * Licensed under the Apache License, Version 2.0 (the "License");
4+ * you may not use this file except in compliance with the License.
5+ * You may obtain a copy of the License at
6+ *
7+ * http://www.apache.org/licenses/LICENSE-2.0
8+ *
9+ * Unless required by applicable law or agreed to in writing, software
10+ * distributed under the License is distributed on an "AS IS" BASIS,
11+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+ * See the License for the specific language governing permissions and
13+ * limitations under the License.
14+ */
15+ 
16+#ifndef OHOS_DAUDIO_SINK_CONFIG_LOADER_H
17+#define OHOS_DAUDIO_SINK_CONFIG_LOADER_H
18+ 
19+#include <string>
20+ 
21+#include "cJSON.h"
22+#include "dhfwk_single_instance.h"
23+ 
24+namespace OHOS {
25+namespace DistributedHardware {
26+class DAudioSinkConfigLoader {
27+ FWK_DECLARE_SINGLE_INSTANCE_BASE(DAudioSinkConfigLoader);
28+public:
29+ int32_t Init();
30+ bool IsMicSinkEnabled() const;
31+ bool IsSpeakerSinkEnabled() const;
32+ 
33+private:
34+ DAudioSinkConfigLoader() = default;
35+ ~DAudioSinkConfigLoader() = default;
36+ std::string ReadConfigFile();
37+ void ParseAudioEnableConfig(const cJSON *root);
38+ 
39+private:
40+ bool micSinkEnabled_ = true;
41+ bool speakerSinkEnabled_ = true;
42+ bool isInitialized_ = false;
43+};
44+} // namespace DistributedHardware
45+} // namespace OHOS
46+#endif // OHOS_DAUDIO_SINK_CONFIG_LOADER_H
@@ -0,0 +1,143 @@
1+/*
2+ * Copyright (c) 2024-2025 Huawei Device Co., Ltd.
3+ * Licensed under the Apache License, Version 2.0 (the "License");
4+ * you may not use this file except in compliance with the License.
5+ * You may obtain a copy of the License at
6+ *
7+ * http://www.apache.org/licenses/LICENSE-2.0
8+ *
9+ * Unless required by applicable law or agreed to in writing, software
10+ * distributed under the License is distributed on an "AS IS" BASIS,
11+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+ * See the License for the specific language governing permissions and
13+ * limitations under the License.
14+ */
15+ 
16+#include "daudio_sink_config_loader.h"
17+ 
18+#include <climits>
19+#include <fstream>
20+ 
21+#include "config_policy_utils.h"
22+ 
23+#include "daudio_constants.h"
24+#include "daudio_errorcode.h"
25+#include "daudio_log.h"
26+ 
27+#undef DH_LOG_TAG
28+#define DH_LOG_TAG "DAudioSinkCfgLoader"
29+ 
30+namespace OHOS {
31+namespace DistributedHardware {
32+namespace {
33+constexpr const char *COMPONENTSLOAD_PROFILE_PATH =
34+ "etc/distributedhardware/distributed_hardware_components_cfg.json";
35+constexpr const char *COMPONENT_ENABLE_CONFIG = "component_enable_config";
36+constexpr const char *AUDIO_TYPE_NAME = "AUDIO";
37+constexpr const char *ROLE_SINK = "sink";
38+}
39+ 
40+FWK_IMPLEMENT_SINGLE_INSTANCE(DAudioSinkConfigLoader);
41+ 
42+std::string DAudioSinkConfigLoader::ReadConfigFile()
43+{
44+ char buf[MAX_PATH_LEN] = {0};
45+ char *profilePath = GetOneCfgFile(COMPONENTSLOAD_PROFILE_PATH, buf, MAX_PATH_LEN);
46+ if (profilePath == nullptr || strlen(profilePath) == 0 || strlen(profilePath) > PATH_MAX) {
47+ DHLOGE("Get config file path failed.");
48+ return "";
49+ }
50+ char path[PATH_MAX] = {0x00};
51+ if (realpath(profilePath, path) == nullptr) {
52+ DHLOGE("Get config file path failed.");
53+ return "";
54+ }
55+ std::ifstream infile(path);
56+ if (!infile.is_open()) {
57+ DHLOGE("Open config file failed.");
58+ return "";
59+ }
60+ std::string sLine;
61+ std::string sAll;
62+ while (getline(infile, sLine)) {
63+ sAll.append(sLine);
64+ }
65+ infile.close();
66+ return sAll;
67+}
B
BBrainL_9月17日

🤖 AI 代码检视意见 | ✨ Quality | ✅ Low | 行号区间: L56-L67

问题描述: 使用 while(getline) 逐行读取并 append 字符串效率较低,且显式调用 infile.close() 在 RAII 机制下是多余的。虽然功能正确,但在处理大文件或频繁读取时会有不必要的性能开销和代码冗余。

💡 查看修复建议(点击展开)

修改建议:使用流迭代器一次性读取文件内容,提升读取效率,并依赖 RAII 自动管理文件句柄,移除显式的 close 调用。

std::ifstream infile(path);
if (!infile.is_open()) {
DHLOGE("Open config file failed.");
return "";
}
std::string sAll((std::istreambuf_iterator<char>(infile)), std::istreambuf_iterator<char>());
return sAll;
likedislike
68+ 
69+void DAudioSinkConfigLoader::ParseAudioEnableConfig(const cJSON *root)
70+{
71+ if (root == nullptr) {
72+ return;
73+ }
74+ cJSON *enableConfig = cJSON_GetObjectItem(root, COMPONENT_ENABLE_CONFIG);
75+ if (enableConfig == nullptr || !cJSON_IsObject(enableConfig)) {
76+ DHLOGI("component_enable_config not found, use default (all enabled).");
77+ return;
78+ }
79+ cJSON *audioEntry = cJSON_GetObjectItem(enableConfig, AUDIO_TYPE_NAME);
80+ if (audioEntry == nullptr || !cJSON_IsObject(audioEntry)) {
81+ DHLOGI("AUDIO entry not found in component_enable_config, use default (all enabled).");
82+ return;
83+ }
84+ cJSON *micEntry = cJSON_GetObjectItem(audioEntry, MIC.c_str());
85+ if (micEntry != nullptr) {
86+ if (cJSON_IsBool(micEntry)) {
87+ micSinkEnabled_ = cJSON_IsTrue(micEntry);
88+ } else if (cJSON_IsObject(micEntry)) {
89+ cJSON *sinkItem = cJSON_GetObjectItem(micEntry, ROLE_SINK);
90+ if (sinkItem != nullptr && cJSON_IsBool(sinkItem)) {
91+ micSinkEnabled_ = cJSON_IsTrue(sinkItem);
92+ }
93+ }
94+ }
95+ cJSON *spkEntry = cJSON_GetObjectItem(audioEntry, SPEAKER.c_str());
96+ if (spkEntry != nullptr) {
97+ if (cJSON_IsBool(spkEntry)) {
98+ speakerSinkEnabled_ = cJSON_IsTrue(spkEntry);
99+ } else if (cJSON_IsObject(spkEntry)) {
100+ cJSON *sinkItem = cJSON_GetObjectItem(spkEntry, ROLE_SINK);
101+ if (sinkItem != nullptr && cJSON_IsBool(sinkItem)) {
102+ speakerSinkEnabled_ = cJSON_IsTrue(sinkItem);
103+ }
104+ }
105+ }
106+ DHLOGI("Parse audio enable config: micSink=%{public}d, speakerSink=%{public}d.",
107+ micSinkEnabled_, speakerSinkEnabled_);
108+}
109+ 
110+int32_t DAudioSinkConfigLoader::Init()
111+{
112+ if (isInitialized_) {
113+ return DH_SUCCESS;
114+ }
115+ std::string jsonStr = ReadConfigFile();
116+ if (jsonStr.empty()) {
117+ DHLOGW("Config file is empty, use default (all enabled).");
118+ isInitialized_ = true;
119+ return DH_SUCCESS;
120+ }
121+ cJSON *root = cJSON_Parse(jsonStr.c_str());
122+ if (root == nullptr) {
123+ DHLOGE("Parse config json failed, use default (all enabled).");
124+ isInitialized_ = true;
125+ return DH_SUCCESS;
126+ }
127+ ParseAudioEnableConfig(root);
128+ cJSON_Delete(root);
129+ isInitialized_ = true;
130+ return DH_SUCCESS;
B
BBrainL_9月17日

🤖 AI 代码检视意见 | 🛡️ Reliability | ⚠️ High | 行号区间: L109-L130

问题描述: DAudioSinkConfigLoader::Init() 方法检查 isInitialized_ 标志并进行写操作,但整个过程没有加锁。如果该方法在多线程环境下被并发调用,可能会导致重复初始化、数据竞争以及读取到未完全更新的配置状态。

💡 查看修复建议(点击展开)

修改建议:为单例的 Init 方法增加互斥锁保护(需在头文件中声明 std::mutex),避免多线程并发调用时产生数据竞争或重复初始化。

int32_t DAudioSinkConfigLoader::Init()
{
std::lock_guard<std::mutex> lock(initMutex_);
if (isInitialized_) {
return DH_SUCCESS;
}
std::string jsonStr = ReadConfigFile();
if (jsonStr.empty()) {
DHLOGW("Config file is empty, use default (all enabled).");
isInitialized_ = true;
return DH_SUCCESS;
}
cJSON *root = cJSON_Parse(jsonStr.c_str());
if (root == nullptr) {
DHLOGE("Parse config json failed, use default (all enabled).");
isInitialized_ = true;
return DH_SUCCESS;
}
ParseAudioEnableConfig(root);
cJSON_Delete(root);
isInitialized_ = true;
return DH_SUCCESS;
}
likedislike
131+}
132+ 
133+bool DAudioSinkConfigLoader::IsMicSinkEnabled() const
134+{
135+ return micSinkEnabled_;
136+}
137+ 
138+bool DAudioSinkConfigLoader::IsSpeakerSinkEnabled() const
139+{
140+ return speakerSinkEnabled_;
141+}
142+} // namespace DistributedHardware
143+} // namespace OHOS
@@ -20,6 +20,7 @@
20#include "daudio_constants.h"20#include "daudio_constants.h"
21#include "daudio_errorcode.h"21#include "daudio_errorcode.h"
22#include "daudio_log.h"22#include "daudio_log.h"
23+#include "daudio_sink_config_loader.h"
23#include "daudio_sink_manager.h"24#include "daudio_sink_manager.h"
24#include "daudio_util.h"25#include "daudio_util.h"
25 26 
@@ -131,6 +132,10 @@ int32_t DAudioSinkDev::TaskDisableDevice(const std::string &args)
131int32_t DAudioSinkDev::TaskOpenDSpeaker(const std::string &args)132int32_t DAudioSinkDev::TaskOpenDSpeaker(const std::string &args)
132{133{
133 DHLOGI("Open speaker device");134 DHLOGI("Open speaker device");
135+ if (!DAudioSinkConfigLoader::GetInstance().IsSpeakerSinkEnabled()) {
136+ DHLOGE("Speaker sink is disabled by config.");
137+ return ERR_DH_AUDIO_FAILED;
138+ }
B
BBrainL_9月17日

🤖 AI 代码检视意见 | 🏗️ Architecture | ℹ️ Medium | 行号区间: L135-L138

问题描述: 当 Speaker/Mic Sink 被配置项禁用时,返回了通用的 ERR_DH_AUDIO_FAILED 错误码。配置禁用属于正常业务拦截,而非系统内部故障。返回通用的 FAILED 错误码可能导致上层调用方无法准确区分是“系统异常”还是“功能被配置关闭”,从而影响重试逻辑或错误上报。

💡 查看修复建议(点击展开)

修改建议:建议新增或使用现有的“不支持”或“未使能”特定错误码替代 ERR_DH_AUDIO_FAILED,以便于上层业务精准区分失败原因。若无合适错误码,可保持现状但需在接口文档中说明。

if (!DAudioSinkConfigLoader::GetInstance().IsSpeakerSinkEnabled()) {
DHLOGE("Speaker sink is disabled by config.");
return ERR_DH_AUDIO_NOT_SUPPORT; // 建议使用特定错误码
}
likedislike
134 if (args.length() > DAUDIO_MAX_JSON_LEN || args.empty()) {139 if (args.length() > DAUDIO_MAX_JSON_LEN || args.empty()) {
135 return ERR_DH_AUDIO_SA_PARAM_INVALID;140 return ERR_DH_AUDIO_SA_PARAM_INVALID;
136 }141 }
@@ -288,6 +293,10 @@ int32_t DAudioSinkDev::TaskStartRender(const std::string &args)
288int32_t DAudioSinkDev::TaskOpenDMic(const std::string &args)293int32_t DAudioSinkDev::TaskOpenDMic(const std::string &args)
289{294{
290 DHLOGI("Open mic device.");295 DHLOGI("Open mic device.");
296+ if (!DAudioSinkConfigLoader::GetInstance().IsMicSinkEnabled()) {
297+ DHLOGE("Mic sink is disabled by config.");
298+ return ERR_DH_AUDIO_FAILED;
299+ }
291 if (!isDevLevelStatus_) {300 if (!isDevLevelStatus_) {
292 DHLOGI("Dev security level status is false.");301 DHLOGI("Dev security level status is false.");
293 return ERR_DH_AUDIO_FAILED;302 return ERR_DH_AUDIO_FAILED;
@@ -305,8 +314,7 @@ int32_t DAudioSinkDev::TaskOpenDMic(const std::string &args)
305 CHECK_AND_FREE_RETURN_RET_LOG(ret != DH_SUCCESS, ret, jParam,314 CHECK_AND_FREE_RETURN_RET_LOG(ret != DH_SUCCESS, ret, jParam,
306 "Get audio param from cjson failed, error code %{public}d.", ret);315 "Get audio param from cjson failed, error code %{public}d.", ret);
307 int32_t dhId = ParseDhidFromEvent(args);316 int32_t dhId = ParseDhidFromEvent(args);
308- CHECK_AND_FREE_RETURN_RET_LOG(dhId == -1, ERR_DH_AUDIO_NULLPTR, jParam,317+ CHECK_AND_FREE_RETURN_RET_LOG(dhId == -1, ERR_DH_AUDIO_NULLPTR, jParam, "%{public}s", "Parse dhId error.");
309- "%{public}s", "Parse dhId error.");
310 cJSON_Delete(jParam);318 cJSON_Delete(jParam);
311 micDhId_ = std::to_string(dhId);319 micDhId_ = std::to_string(dhId);
312 std::shared_ptr<DMicClient> micClient = nullptr;320 std::shared_ptr<DMicClient> micClient = nullptr;
@@ -23,6 +23,7 @@
23#include "daudio_constants.h"23#include "daudio_constants.h"
24#include "daudio_errorcode.h"24#include "daudio_errorcode.h"
25#include "daudio_log.h"25#include "daudio_log.h"
26+#include "daudio_sink_config_loader.h"
26#include "daudio_util.h"27#include "daudio_util.h"
27#include "device_manager.h"28#include "device_manager.h"
28 29 
@@ -69,6 +70,7 @@ int32_t DAudioSinkManager::Init(const sptr<IDAudioSinkIpcCallback> &sinkCallback
69 return DH_SUCCESS;70 return DH_SUCCESS;
70 }71 }
71 DHLOGI("Init audio sink manager.");72 DHLOGI("Init audio sink manager.");
73+ DAudioSinkConfigLoader::GetInstance().Init();
72 {74 {
73 std::lock_guard<std::mutex> ipcLock(ipcCallbackMutex_);75 std::lock_guard<std::mutex> ipcLock(ipcCallbackMutex_);
74 initCallback_ = std::make_shared<DeviceInitCallback>();76 initCallback_ = std::make_shared<DeviceInitCallback>();
@@ -58,6 +58,7 @@ ohos_shared_library("distributed_audio_sink") {
58 "${innerkits_path}/native_cpp/audio_sink/src/daudio_sink_load_callback.cpp",58 "${innerkits_path}/native_cpp/audio_sink/src/daudio_sink_load_callback.cpp",
59 "${innerkits_path}/native_cpp/audio_sink/src/daudio_sink_proxy.cpp",59 "${innerkits_path}/native_cpp/audio_sink/src/daudio_sink_proxy.cpp",
60 "${innerkits_path}/native_cpp/audio_source/src/daudio_source_proxy.cpp",60 "${innerkits_path}/native_cpp/audio_source/src/daudio_source_proxy.cpp",
61+ "${services_path}/audiomanager/managersink/src/daudio_sink_config_loader.cpp",
61 "${services_path}/audiomanager/managersink/src/daudio_sink_dev.cpp",62 "${services_path}/audiomanager/managersink/src/daudio_sink_dev.cpp",
62 "${services_path}/audiomanager/managersink/src/daudio_sink_manager.cpp",63 "${services_path}/audiomanager/managersink/src/daudio_sink_manager.cpp",
63 "src/daudio_sink_hidumper.cpp",64 "src/daudio_sink_hidumper.cpp",
@@ -92,6 +93,7 @@ ohos_shared_library("distributed_audio_sink") {
92 "audio_framework:audio_renderer",93 "audio_framework:audio_renderer",
93 "cJSON:cjson",94 "cJSON:cjson",
94 "c_utils:utils",95 "c_utils:utils",
96+ "config_policy:configpolicy_util",
95 "device_manager:devicemanagersdk",97 "device_manager:devicemanagersdk",
96 "distributed_hardware_fwk:distributed_av_receiver",98 "distributed_hardware_fwk:distributed_av_receiver",
97 "distributed_hardware_fwk:distributed_av_sender",99 "distributed_hardware_fwk:distributed_av_sender",
@@ -131,9 +131,41 @@ ohos_unittest("DAudioSinkManagerTest") {
131 }131 }
132}132}
133 133 
134+## UnitTest daudio_sink_config_loader_test
135+ohos_unittest("DAudioSinkConfigLoaderTest") {
136+ module_out_path = module_out_path
137+ 
138+ sources = [ "${services_path}/audiomanager/test/unittest/managersink/src/daudio_sink_config_loader_test.cpp" ]
139+ 
140+ configs = [ ":module_private_config" ]
141+ 
142+ deps = [
143+ "${innerkits_path}/native_cpp/audio_sink:distributed_audio_sink_sdk",
144+ "${services_path}/audiomanager/servicesink:distributed_audio_sink",
145+ "${services_path}/common:distributed_audio_utils",
146+ ]
147+ 
148+ external_deps = [
149+ "cJSON:cjson",
150+ "c_utils:utils",
151+ "config_policy:configpolicy_util",
152+ "device_manager:devicemanagersdk",
153+ "distributed_hardware_fwk:distributedhardwareutils",
154+ "dsoftbus:softbus_client",
155+ "eventhandler:libeventhandler",
156+ "googletest:gmock",
157+ "hilog:libhilog",
158+ "hitrace:hitrace_meter",
159+ "ipc:ipc_core",
160+ "safwk:system_ability_fwk",
161+ "samgr:samgr_proxy",
162+ ]
163+}
164+ 
134group("manager_sink_test") {165group("manager_sink_test") {
135 testonly = true166 testonly = true
136 deps = [167 deps = [
168+ ":DAudioSinkConfigLoaderTest",
137 ":DAudioSinkManagerTest",169 ":DAudioSinkManagerTest",
138 ":DaudioSinkDevTest",170 ":DaudioSinkDevTest",
139 ]171 ]
@@ -0,0 +1,36 @@
1+/*
2+ * Copyright (c) 2024-2025 Huawei Device Co., Ltd.
3+ * Licensed under the Apache License, Version 2.0 (the "License");
4+ * you may not use this file except in compliance with the License.
5+ * You may obtain a copy of the License at
6+ *
7+ * http://www.apache.org/licenses/LICENSE-2.0
8+ *
9+ * Unless required by applicable law or agreed to in writing, software
10+ * distributed under the License is distributed on an "AS IS" BASIS,
11+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+ * See the License for the specific language governing permissions and
13+ * limitations under the License.
14+ */
15+ 
16+#ifndef OHOS_DAUDIO_SINK_CONFIG_LOADER_TEST_H
17+#define OHOS_DAUDIO_SINK_CONFIG_LOADER_TEST_H
18+ 
hobbycao
hobbycaohobbycao9月17日

把UT报告测试结果发一下

likedislike
19+#include <gtest/gtest.h>
20+ 
21+#define private public
22+#include "daudio_sink_config_loader.h"
23+#undef private
24+ 
25+namespace OHOS {
26+namespace DistributedHardware {
27+class DAudioSinkConfigLoaderTest : public testing::Test {
28+public:
29+ static void SetUpTestCase(void);
30+ static void TearDownTestCase(void);
31+ void SetUp();
32+ void TearDown();
33+};
34+} // namespace DistributedHardware
35+} // namespace OHOS
36+#endif // OHOS_DAUDIO_SINK_CONFIG_LOADER_TEST_H
@@ -21,6 +21,7 @@
21#include "if_system_ability_manager.h"21#include "if_system_ability_manager.h"
22 22 
23#define private public23#define private public
24+#include "daudio_sink_config_loader.h"
24#include "daudio_sink_dev.h"25#include "daudio_sink_dev.h"
25#undef private26#undef private
26 27 
@@ -0,0 +1,370 @@
1+/*
2+ * Copyright (c) 2024-2025 Huawei Device Co., Ltd.
3+ * Licensed under the Apache License, Version 2.0 (the "License");
4+ * you may not use this file except in compliance with the License.
5+ * You may obtain a copy of the License at
6+ *
7+ * http://www.apache.org/licenses/LICENSE-2.0
8+ *
9+ * Unless required by applicable law or agreed to in writing, software
10+ * distributed under the License is distributed on an "AS IS" BASIS,
11+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+ * See the License for the specific language governing permissions and
13+ * limitations under the License.
14+ */
15+ 
16+#include "daudio_sink_config_loader_test.h"
17+ 
18+#include "cJSON.h"
19+#include "daudio_constants.h"
20+#include "daudio_errorcode.h"
21+#include "daudio_log.h"
22+ 
23+#undef DH_LOG_TAG
24+#define DH_LOG_TAG "DAudioSinkCfgLoaderTest"
25+ 
26+using namespace testing::ext;
27+ 
28+namespace OHOS {
29+namespace DistributedHardware {
30+namespace {
31+constexpr const char *COMPONENT_ENABLE_CONFIG = "component_enable_config";
32+constexpr const char *AUDIO_TYPE_NAME = "AUDIO";
33+}
34+ 
35+void DAudioSinkConfigLoaderTest::SetUpTestCase(void) {}
36+void DAudioSinkConfigLoaderTest::TearDownTestCase(void) {}
37+void DAudioSinkConfigLoaderTest::SetUp()
38+{
39+ auto &loader = DAudioSinkConfigLoader::GetInstance();
40+ loader.micSinkEnabled_ = true;
41+ loader.speakerSinkEnabled_ = true;
42+ loader.isInitialized_ = false;
43+}
44+void DAudioSinkConfigLoaderTest::TearDown()
45+{
46+ auto &loader = DAudioSinkConfigLoader::GetInstance();
47+ loader.micSinkEnabled_ = true;
48+ loader.speakerSinkEnabled_ = true;
49+ loader.isInitialized_ = false;
50+}
51+ 
52+struct SubtypeConfig {
53+ bool present = false;
54+ bool isBool = false;
55+ bool sinkVal = false;
56+};
57+ 
58+static cJSON *BuildEnableConfigJson(const SubtypeConfig &micCfg, const SubtypeConfig &spkCfg)
59+{
60+ cJSON *root = cJSON_CreateObject();
61+ cJSON *enableConfig = cJSON_CreateObject();
62+ cJSON *audioEntry = cJSON_CreateObject();
63+ if (micCfg.present) {
64+ if (micCfg.isBool) {
65+ cJSON_AddBoolToObject(audioEntry, MIC.c_str(), micCfg.sinkVal);
66+ } else {
67+ cJSON *micObj = cJSON_CreateObject();
68+ cJSON_AddBoolToObject(micObj, "sink", micCfg.sinkVal);
69+ cJSON_AddBoolToObject(micObj, "source", true);
70+ cJSON_AddItemToObject(audioEntry, MIC.c_str(), micObj);
71+ }
72+ }
73+ if (spkCfg.present) {
74+ if (spkCfg.isBool) {
75+ cJSON_AddBoolToObject(audioEntry, SPEAKER.c_str(), spkCfg.sinkVal);
76+ } else {
77+ cJSON *spkObj = cJSON_CreateObject();
78+ cJSON_AddBoolToObject(spkObj, "sink", spkCfg.sinkVal);
79+ cJSON_AddBoolToObject(spkObj, "source", true);
80+ cJSON_AddItemToObject(audioEntry, SPEAKER.c_str(), spkObj);
81+ }
82+ }
83+ cJSON_AddItemToObject(enableConfig, AUDIO_TYPE_NAME, audioEntry);
84+ cJSON_AddItemToObject(root, COMPONENT_ENABLE_CONFIG, enableConfig);
85+ return root;
86+}
87+ 
88+HWTEST_F(DAudioSinkConfigLoaderTest, ParseAudioEnableConfig_001, TestSize.Level1)
89+{
90+ auto &loader = DAudioSinkConfigLoader::GetInstance();
91+ loader.micSinkEnabled_ = true;
92+ loader.speakerSinkEnabled_ = true;
93+ cJSON *root = BuildEnableConfigJson({true, false, false}, {true, false, false});
94+ ASSERT_NE(root, nullptr);
95+ loader.ParseAudioEnableConfig(root);
96+ EXPECT_FALSE(loader.micSinkEnabled_);
97+ EXPECT_FALSE(loader.speakerSinkEnabled_);
98+ cJSON_Delete(root);
99+}
100+ 
101+HWTEST_F(DAudioSinkConfigLoaderTest, ParseAudioEnableConfig_002, TestSize.Level1)
102+{
103+ auto &loader = DAudioSinkConfigLoader::GetInstance();
104+ loader.micSinkEnabled_ = true;
105+ loader.speakerSinkEnabled_ = true;
106+ cJSON *root = BuildEnableConfigJson({true, true, false}, {true, true, true});
107+ ASSERT_NE(root, nullptr);
108+ loader.ParseAudioEnableConfig(root);
109+ EXPECT_FALSE(loader.micSinkEnabled_);
110+ EXPECT_TRUE(loader.speakerSinkEnabled_);
111+ cJSON_Delete(root);
112+}
113+ 
114+HWTEST_F(DAudioSinkConfigLoaderTest, ParseAudioEnableConfig_003, TestSize.Level1)
115+{
116+ auto &loader = DAudioSinkConfigLoader::GetInstance();
117+ loader.micSinkEnabled_ = true;
118+ loader.speakerSinkEnabled_ = true;
119+ cJSON *root = BuildEnableConfigJson({true, false, true}, {true, false, true});
120+ ASSERT_NE(root, nullptr);
121+ loader.ParseAudioEnableConfig(root);
122+ EXPECT_TRUE(loader.micSinkEnabled_);
123+ EXPECT_TRUE(loader.speakerSinkEnabled_);
124+ cJSON_Delete(root);
125+}
126+ 
127+HWTEST_F(DAudioSinkConfigLoaderTest, ParseAudioEnableConfig_004, TestSize.Level1)
128+{
129+ auto &loader = DAudioSinkConfigLoader::GetInstance();
130+ loader.micSinkEnabled_ = false;
131+ loader.speakerSinkEnabled_ = false;
132+ cJSON *root = BuildEnableConfigJson({false, false, false}, {false, false, false});
133+ ASSERT_NE(root, nullptr);
134+ loader.ParseAudioEnableConfig(root);
135+ EXPECT_FALSE(loader.micSinkEnabled_);
136+ EXPECT_FALSE(loader.speakerSinkEnabled_);
137+ cJSON_Delete(root);
138+}
139+ 
140+HWTEST_F(DAudioSinkConfigLoaderTest, ParseAudioEnableConfig_005, TestSize.Level1)
141+{
142+ auto &loader = DAudioSinkConfigLoader::GetInstance();
143+ loader.micSinkEnabled_ = false;
144+ loader.speakerSinkEnabled_ = false;
145+ cJSON *root = cJSON_CreateObject();
146+ ASSERT_NE(root, nullptr);
147+ loader.ParseAudioEnableConfig(root);
148+ EXPECT_FALSE(loader.micSinkEnabled_);
149+ EXPECT_FALSE(loader.speakerSinkEnabled_);
150+ cJSON_Delete(root);
151+}
152+ 
153+HWTEST_F(DAudioSinkConfigLoaderTest, ParseAudioEnableConfig_006, TestSize.Level1)
154+{
155+ auto &loader = DAudioSinkConfigLoader::GetInstance();
156+ loader.micSinkEnabled_ = false;
157+ loader.speakerSinkEnabled_ = false;
158+ cJSON *root = cJSON_CreateObject();
159+ cJSON *enableConfig = cJSON_CreateObject();
160+ cJSON_AddItemToObject(root, COMPONENT_ENABLE_CONFIG, enableConfig);
161+ loader.ParseAudioEnableConfig(root);
162+ EXPECT_FALSE(loader.micSinkEnabled_);
163+ EXPECT_FALSE(loader.speakerSinkEnabled_);
164+ cJSON_Delete(root);
165+}
166+ 
167+HWTEST_F(DAudioSinkConfigLoaderTest, ParseAudioEnableConfig_007, TestSize.Level1)
168+{
169+ auto &loader = DAudioSinkConfigLoader::GetInstance();
170+ loader.micSinkEnabled_ = false;
171+ loader.speakerSinkEnabled_ = false;
172+ cJSON *root = cJSON_CreateObject();
173+ cJSON *enableConfig = cJSON_CreateObject();
174+ cJSON *audioEntry = cJSON_CreateObject();
175+ cJSON_AddItemToObject(enableConfig, AUDIO_TYPE_NAME, audioEntry);
176+ cJSON_AddItemToObject(root, COMPONENT_ENABLE_CONFIG, enableConfig);
177+ loader.ParseAudioEnableConfig(root);
178+ EXPECT_FALSE(loader.micSinkEnabled_);
179+ EXPECT_FALSE(loader.speakerSinkEnabled_);
180+ cJSON_Delete(root);
181+}
182+ 
183+HWTEST_F(DAudioSinkConfigLoaderTest, ParseAudioEnableConfig_008, TestSize.Level1)
184+{
185+ auto &loader = DAudioSinkConfigLoader::GetInstance();
186+ loader.micSinkEnabled_ = true;
187+ loader.speakerSinkEnabled_ = true;
188+ cJSON *root = BuildEnableConfigJson({true, false, false}, {false, false, false});
189+ ASSERT_NE(root, nullptr);
190+ loader.ParseAudioEnableConfig(root);
191+ EXPECT_FALSE(loader.micSinkEnabled_);
192+ EXPECT_TRUE(loader.speakerSinkEnabled_);
193+ cJSON_Delete(root);
194+}
195+ 
196+HWTEST_F(DAudioSinkConfigLoaderTest, ParseAudioEnableConfig_009, TestSize.Level1)
197+{
198+ auto &loader = DAudioSinkConfigLoader::GetInstance();
199+ loader.micSinkEnabled_ = true;
200+ loader.speakerSinkEnabled_ = true;
201+ cJSON *root = BuildEnableConfigJson({false, false, false}, {true, false, false});
202+ ASSERT_NE(root, nullptr);
203+ loader.ParseAudioEnableConfig(root);
204+ EXPECT_TRUE(loader.micSinkEnabled_);
205+ EXPECT_FALSE(loader.speakerSinkEnabled_);
206+ cJSON_Delete(root);
207+}
208+ 
209+HWTEST_F(DAudioSinkConfigLoaderTest, ParseAudioEnableConfig_nullptr, TestSize.Level1)
210+{
211+ auto &loader = DAudioSinkConfigLoader::GetInstance();
212+ loader.micSinkEnabled_ = false;
213+ loader.speakerSinkEnabled_ = false;
214+ loader.ParseAudioEnableConfig(nullptr);
215+ EXPECT_FALSE(loader.micSinkEnabled_);
216+ EXPECT_FALSE(loader.speakerSinkEnabled_);
217+}
218+ 
219+HWTEST_F(DAudioSinkConfigLoaderTest, Init_already_initialized, TestSize.Level1)
220+{
221+ auto &loader = DAudioSinkConfigLoader::GetInstance();
222+ loader.isInitialized_ = true;
223+ loader.micSinkEnabled_ = false;
224+ loader.speakerSinkEnabled_ = false;
225+ EXPECT_EQ(DH_SUCCESS, loader.Init());
226+ EXPECT_FALSE(loader.micSinkEnabled_);
227+ EXPECT_FALSE(loader.speakerSinkEnabled_);
228+}
229+ 
230+HWTEST_F(DAudioSinkConfigLoaderTest, Init_not_initialized, TestSize.Level1)
231+{
232+ auto &loader = DAudioSinkConfigLoader::GetInstance();
233+ loader.isInitialized_ = false;
234+ EXPECT_EQ(DH_SUCCESS, loader.Init());
235+ EXPECT_TRUE(loader.isInitialized_);
236+}
237+ 
238+HWTEST_F(DAudioSinkConfigLoaderTest, IsMicSinkEnabled_default, TestSize.Level1)
239+{
240+ auto &loader = DAudioSinkConfigLoader::GetInstance();
241+ loader.micSinkEnabled_ = true;
242+ EXPECT_TRUE(loader.IsMicSinkEnabled());
243+}
244+ 
245+HWTEST_F(DAudioSinkConfigLoaderTest, IsMicSinkEnabled_disabled, TestSize.Level1)
246+{
247+ auto &loader = DAudioSinkConfigLoader::GetInstance();
248+ loader.micSinkEnabled_ = false;
249+ EXPECT_FALSE(loader.IsMicSinkEnabled());
250+}
251+ 
252+HWTEST_F(DAudioSinkConfigLoaderTest, IsSpeakerSinkEnabled_default, TestSize.Level1)
253+{
254+ auto &loader = DAudioSinkConfigLoader::GetInstance();
255+ loader.speakerSinkEnabled_ = true;
256+ EXPECT_TRUE(loader.IsSpeakerSinkEnabled());
257+}
258+ 
259+HWTEST_F(DAudioSinkConfigLoaderTest, IsSpeakerSinkEnabled_disabled, TestSize.Level1)
260+{
261+ auto &loader = DAudioSinkConfigLoader::GetInstance();
262+ loader.speakerSinkEnabled_ = false;
263+ EXPECT_FALSE(loader.IsSpeakerSinkEnabled());
264+}
265+ 
266+HWTEST_F(DAudioSinkConfigLoaderTest, ParseAudioEnableConfig_mic_not_bool_not_object, TestSize.Level1)
267+{
268+ auto &loader = DAudioSinkConfigLoader::GetInstance();
269+ loader.micSinkEnabled_ = false;
270+ loader.speakerSinkEnabled_ = false;
271+ cJSON *root = cJSON_CreateObject();
272+ cJSON *enableConfig = cJSON_CreateObject();
273+ cJSON *audioEntry = cJSON_CreateObject();
274+ cJSON_AddNumberToObject(audioEntry, MIC.c_str(), 123);
275+ cJSON_AddItemToObject(enableConfig, AUDIO_TYPE_NAME, audioEntry);
276+ cJSON_AddItemToObject(root, COMPONENT_ENABLE_CONFIG, enableConfig);
277+ loader.ParseAudioEnableConfig(root);
278+ EXPECT_FALSE(loader.micSinkEnabled_);
279+ cJSON_Delete(root);
280+}
281+ 
282+HWTEST_F(DAudioSinkConfigLoaderTest, ParseAudioEnableConfig_mic_object_no_sink, TestSize.Level1)
283+{
284+ auto &loader = DAudioSinkConfigLoader::GetInstance();
285+ loader.micSinkEnabled_ = false;
286+ loader.speakerSinkEnabled_ = false;
287+ cJSON *root = cJSON_CreateObject();
288+ cJSON *enableConfig = cJSON_CreateObject();
289+ cJSON *audioEntry = cJSON_CreateObject();
290+ cJSON *micObj = cJSON_CreateObject();
291+ cJSON_AddBoolToObject(micObj, "source", true);
292+ cJSON_AddItemToObject(audioEntry, MIC.c_str(), micObj);
293+ cJSON_AddItemToObject(enableConfig, AUDIO_TYPE_NAME, audioEntry);
294+ cJSON_AddItemToObject(root, COMPONENT_ENABLE_CONFIG, enableConfig);
295+ loader.ParseAudioEnableConfig(root);
296+ EXPECT_FALSE(loader.micSinkEnabled_);
297+ cJSON_Delete(root);
298+}
299+ 
300+HWTEST_F(DAudioSinkConfigLoaderTest, ParseAudioEnableConfig_mic_object_sink_not_bool, TestSize.Level1)
301+{
302+ auto &loader = DAudioSinkConfigLoader::GetInstance();
303+ loader.micSinkEnabled_ = false;
304+ loader.speakerSinkEnabled_ = false;
305+ cJSON *root = cJSON_CreateObject();
306+ cJSON *enableConfig = cJSON_CreateObject();
307+ cJSON *audioEntry = cJSON_CreateObject();
308+ cJSON *micObj = cJSON_CreateObject();
309+ cJSON_AddNumberToObject(micObj, "sink", 123);
310+ cJSON_AddItemToObject(audioEntry, MIC.c_str(), micObj);
311+ cJSON_AddItemToObject(enableConfig, AUDIO_TYPE_NAME, audioEntry);
312+ cJSON_AddItemToObject(root, COMPONENT_ENABLE_CONFIG, enableConfig);
313+ loader.ParseAudioEnableConfig(root);
314+ EXPECT_FALSE(loader.micSinkEnabled_);
315+ cJSON_Delete(root);
316+}
317+ 
318+HWTEST_F(DAudioSinkConfigLoaderTest, ParseAudioEnableConfig_spk_not_bool_not_object, TestSize.Level1)
319+{
320+ auto &loader = DAudioSinkConfigLoader::GetInstance();
321+ loader.micSinkEnabled_ = false;
322+ loader.speakerSinkEnabled_ = false;
323+ cJSON *root = cJSON_CreateObject();
324+ cJSON *enableConfig = cJSON_CreateObject();
325+ cJSON *audioEntry = cJSON_CreateObject();
326+ cJSON_AddNumberToObject(audioEntry, SPEAKER.c_str(), 123);
327+ cJSON_AddItemToObject(enableConfig, AUDIO_TYPE_NAME, audioEntry);
328+ cJSON_AddItemToObject(root, COMPONENT_ENABLE_CONFIG, enableConfig);
329+ loader.ParseAudioEnableConfig(root);
330+ EXPECT_FALSE(loader.speakerSinkEnabled_);
331+ cJSON_Delete(root);
332+}
333+ 
334+HWTEST_F(DAudioSinkConfigLoaderTest, ParseAudioEnableConfig_spk_object_no_sink, TestSize.Level1)
335+{
336+ auto &loader = DAudioSinkConfigLoader::GetInstance();
337+ loader.micSinkEnabled_ = false;
338+ loader.speakerSinkEnabled_ = false;
339+ cJSON *root = cJSON_CreateObject();
340+ cJSON *enableConfig = cJSON_CreateObject();
341+ cJSON *audioEntry = cJSON_CreateObject();
342+ cJSON *spkObj = cJSON_CreateObject();
343+ cJSON_AddBoolToObject(spkObj, "source", true);
344+ cJSON_AddItemToObject(audioEntry, SPEAKER.c_str(), spkObj);
345+ cJSON_AddItemToObject(enableConfig, AUDIO_TYPE_NAME, audioEntry);
346+ cJSON_AddItemToObject(root, COMPONENT_ENABLE_CONFIG, enableConfig);
347+ loader.ParseAudioEnableConfig(root);
348+ EXPECT_FALSE(loader.speakerSinkEnabled_);
349+ cJSON_Delete(root);
350+}
351+ 
352+HWTEST_F(DAudioSinkConfigLoaderTest, ParseAudioEnableConfig_spk_object_sink_not_bool, TestSize.Level1)
353+{
354+ auto &loader = DAudioSinkConfigLoader::GetInstance();
355+ loader.micSinkEnabled_ = false;
356+ loader.speakerSinkEnabled_ = false;
357+ cJSON *root = cJSON_CreateObject();
358+ cJSON *enableConfig = cJSON_CreateObject();
359+ cJSON *audioEntry = cJSON_CreateObject();
360+ cJSON *spkObj = cJSON_CreateObject();
361+ cJSON_AddNumberToObject(spkObj, "sink", 123);
362+ cJSON_AddItemToObject(audioEntry, SPEAKER.c_str(), spkObj);
363+ cJSON_AddItemToObject(enableConfig, AUDIO_TYPE_NAME, audioEntry);
364+ cJSON_AddItemToObject(root, COMPONENT_ENABLE_CONFIG, enableConfig);
365+ loader.ParseAudioEnableConfig(root);
366+ EXPECT_FALSE(loader.speakerSinkEnabled_);
367+ cJSON_Delete(root);
368+}
369+} // namespace DistributedHardware
370+} // namespace OHOS
@@ -1229,79 +1229,6 @@ HWTEST_F(DAudioSinkDevTest, NotifyEnhanceParamChange_002, TestSize.Level1)
1229 sinkDev_->handler_->NotifyEnhanceParamChange(msgEvent);1229 sinkDev_->handler_->NotifyEnhanceParamChange(msgEvent);
1230}1230}
1231 1231 
1232-/**
1233- * @tc.name: IsHardwareAccessGranted_001
1234- * @tc.desc: Verify the IsHardwareAccessGranted function without authorization decision.
1235- * @tc.type: FUNC
1236- * @tc.require: AR000H0E5F
1237- */
1238-HWTEST_F(DAudioSinkDevTest, IsHardwareAccessGranted_001, TestSize.Level1)
1239-{
1240- ASSERT_NE(sinkDev_, nullptr);
1241- bool result = sinkDev_->IsHardwareAccessGranted();
1242- EXPECT_EQ(false, result);
1243-}
1244- 
1245-/**
1246- * @tc.name: IsEventAllowedByHardwareAccess_001
1247- * @tc.desc: Verify IsEventAllowedByHardwareAccess with OPEN_SPEAKER event.
1248- * @tc.type: FUNC
1249- * @tc.require: AR000H0E5F
1250- */
1251-HWTEST_F(DAudioSinkDevTest, IsEventAllowedByHardwareAccess_001, TestSize.Level1)
1252-{
1253- int32_t eventType = OPEN_SPEAKER;
1254- std::string eventContent = "{\"dhId\":\"1\"}";
1255- AudioEvent audioEvent(eventType, eventContent);
1256- auto eventParam = std::make_shared<AudioEvent>(audioEvent);
1257- auto msgEvent = AppExecFwk::InnerEvent::Get(static_cast<uint32_t>(audioEvent.type), eventParam, 0);
1258- ASSERT_NE(sinkDev_, nullptr);
1259- EXPECT_EQ(DH_SUCCESS, sinkDev_->AwakeAudioDev());
1260- ASSERT_NE(sinkDev_->handler_, nullptr);
1261- sinkDev_->handler_->ProcessEvent(msgEvent);
1262- ASSERT_NE(sinkDev_->handler_, nullptr);
1263-}
1264- 
1265-/**
1266- * @tc.name: IsEventAllowedByHardwareAccess_002
1267- * @tc.desc: Verify IsEventAllowedByHardwareAccess with OPEN_MIC event.
1268- * @tc.type: FUNC
1269- * @tc.require: AR000H0E5F
1270- */
1271-HWTEST_F(DAudioSinkDevTest, IsEventAllowedByHardwareAccess_002, TestSize.Level1)
1272-{
1273- int32_t eventType = OPEN_MIC;
1274- std::string eventContent = "{\"dhId\":\"1\"}";
1275- AudioEvent audioEvent(eventType, eventContent);
1276- auto eventParam = std::make_shared<AudioEvent>(audioEvent);
1277- auto msgEvent = AppExecFwk::InnerEvent::Get(static_cast<uint32_t>(audioEvent.type), eventParam, 0);
1278- ASSERT_NE(sinkDev_, nullptr);
1279- EXPECT_EQ(DH_SUCCESS, sinkDev_->AwakeAudioDev());
1280- ASSERT_NE(sinkDev_->handler_, nullptr);
1281- sinkDev_->handler_->ProcessEvent(msgEvent);
1282- ASSERT_NE(sinkDev_->handler_, nullptr);
1283-}
1284- 
1285-/**
1286- * @tc.name: IsEventAllowedByHardwareAccess_003
1287- * @tc.desc: Verify IsEventAllowedByHardwareAccess with other event type.
1288- * @tc.type: FUNC
1289- * @tc.require: AR000H0E5F
1290- */
1291-HWTEST_F(DAudioSinkDevTest, IsEventAllowedByHardwareAccess_003, TestSize.Level1)
1292-{
1293- int32_t eventType = VOLUME_SET;
1294- std::string eventContent = "{\"dhId\":\"1\"}";
1295- AudioEvent audioEvent(eventType, eventContent);
1296- auto eventParam = std::make_shared<AudioEvent>(audioEvent);
1297- auto msgEvent = AppExecFwk::InnerEvent::Get(static_cast<uint32_t>(audioEvent.type), eventParam, 0);
1298- ASSERT_NE(sinkDev_, nullptr);
1299- EXPECT_EQ(DH_SUCCESS, sinkDev_->AwakeAudioDev());
1300- ASSERT_NE(sinkDev_->handler_, nullptr);
1301- sinkDev_->handler_->ProcessEvent(msgEvent);
1302- ASSERT_NE(sinkDev_->handler_, nullptr);
1303-}
1304- 
1305HWTEST_F(DAudioSinkDevTest, ResolveEnableUser_001, TestSize.Level1)1232HWTEST_F(DAudioSinkDevTest, ResolveEnableUser_001, TestSize.Level1)
B
BBrainL_9月17日

🤖 AI 代码检视意见 | ✨ Quality | ℹ️ Medium | 行号区间: L1232

问题描述: 此 PR 删除了 IsHardwareAccessGranted 和 IsEventAllowedByHardwareAccess 系列测试用例,但在源文件 daudio_sink_dev.cpp 的 diff 中未见删除对应的函数实现。如果源码中这些函数仍然存在,删除测试用例将导致代码覆盖率下降,违反测试完整性原则。

💡 查看修复建议(点击展开)

修改建议:检查 IsHardwareAccessGranted 和 IsEventAllowedByHardwareAccess 方法在 daudio_sink_dev.cpp 中是否仍存在。若仍存在,请恢复对应的测试用例以维持代码覆盖率;若已删除,请忽略此建议。

HWTEST_F(DAudioSinkDevTest, ResolveEnableUser_001, TestSize.Level1)
likedislike
1306{1233{
1307 ASSERT_NE(sinkDev_, nullptr);1234 ASSERT_NE(sinkDev_, nullptr);
@@ -1377,5 +1304,49 @@ HWTEST_F(DAudioSinkDevTest, CheckAclRight_ResolveEnableUser_002, TestSize.Level1
1377 DAudioSinkManager::GetInstance().SetEnableFirstTokenId(0);1304 DAudioSinkManager::GetInstance().SetEnableFirstTokenId(0);
1378}1305}
1379 1306 
1307+HWTEST_F(DAudioSinkDevTest, TaskOpenDSpeaker_config_disabled, TestSize.Level1)
1308+{
1309+ ASSERT_NE(sinkDev_, nullptr);
1310+ auto &loader = DAudioSinkConfigLoader::GetInstance();
1311+ bool saved = loader.speakerSinkEnabled_;
1312+ loader.speakerSinkEnabled_ = false;
1313+ std::string args = "{\"dhId\":\"1\"}";
1314+ EXPECT_EQ(ERR_DH_AUDIO_FAILED, sinkDev_->TaskOpenDSpeaker(args));
1315+ loader.speakerSinkEnabled_ = saved;
1316+}
1317+ 
1318+HWTEST_F(DAudioSinkDevTest, TaskOpenDSpeaker_config_enabled, TestSize.Level1)
1319+{
1320+ ASSERT_NE(sinkDev_, nullptr);
1321+ auto &loader = DAudioSinkConfigLoader::GetInstance();
1322+ bool saved = loader.speakerSinkEnabled_;
1323+ loader.speakerSinkEnabled_ = true;
1324+ std::string args;
1325+ EXPECT_NE(DH_SUCCESS, sinkDev_->TaskOpenDSpeaker(args));
1326+ loader.speakerSinkEnabled_ = saved;
1327+}
1328+ 
1329+HWTEST_F(DAudioSinkDevTest, TaskOpenDMic_config_disabled, TestSize.Level1)
1330+{
1331+ ASSERT_NE(sinkDev_, nullptr);
1332+ auto &loader = DAudioSinkConfigLoader::GetInstance();
1333+ bool saved = loader.micSinkEnabled_;
1334+ loader.micSinkEnabled_ = false;
1335+ std::string args = "{\"dhId\":\"1\"}";
1336+ EXPECT_EQ(ERR_DH_AUDIO_FAILED, sinkDev_->TaskOpenDMic(args));
1337+ loader.micSinkEnabled_ = saved;
1338+}
1339+ 
1340+HWTEST_F(DAudioSinkDevTest, TaskOpenDMic_config_enabled, TestSize.Level1)
1341+{
1342+ ASSERT_NE(sinkDev_, nullptr);
1343+ auto &loader = DAudioSinkConfigLoader::GetInstance();
1344+ bool saved = loader.micSinkEnabled_;
1345+ loader.micSinkEnabled_ = true;
1346+ std::string args;
1347+ EXPECT_NE(DH_SUCCESS, sinkDev_->TaskOpenDMic(args));
1348+ loader.micSinkEnabled_ = saved;
1349+}
1350+ 
1380} // DistributedHardware1351} // DistributedHardware
1381} // OHOS1352} // OHOS