1 /*
2 * Copyright (c) 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 LOG_TAG
17 #define LOG_TAG "IdHandler"
18 #endif
19
20 #include "util/id_handler.h"
21 #include "audio_hdi_log.h"
22 #include "audio_errors.h"
23
24 namespace OHOS {
25 namespace AudioStandard {
GetInstance(void)26 IdHandler &IdHandler::GetInstance(void)
27 {
28 static IdHandler instance;
29 return instance;
30 }
31
GetId(HdiIdBase base,HdiIdType type,const std::string & info)32 uint32_t IdHandler::GetId(HdiIdBase base, HdiIdType type, const std::string &info)
33 {
34 CHECK_AND_RETURN_RET_LOG(base < HDI_ID_BASE_NUM, HDI_INVALID_ID, "invalid id base %{public}u", base);
35 CHECK_AND_RETURN_RET_LOG(type < HDI_ID_TYPE_NUM, HDI_INVALID_ID, "invalid id type %{public}u", type);
36
37 uint32_t id = (base << HDI_ID_BASE_OFFSET) | (type << HDI_ID_TYPE_OFFSET);
38 std::lock_guard<std::mutex> lock(infoIdMtx_);
39 for (auto &attr : infoIdMap_) {
40 if (attr.second.info_ == info) {
41 id |= attr.first;
42 return id;
43 }
44 }
45 uint32_t infoId = CreateInfoId();
46 infoIdMap_[infoId].info_ = info;
47 id |= infoId;
48 return id;
49 }
50
GetRenderIdByDeviceClass(const std::string & deviceClass,const std::string & info)51 uint32_t IdHandler::GetRenderIdByDeviceClass(const std::string &deviceClass, const std::string &info)
52 {
53 CHECK_AND_RETURN_RET_LOG(!deviceClass.empty(), HDI_INVALID_ID, "invalid device class");
54 AUDIO_INFO_LOG("deviceClass: %{public}s, info: %{public}s", deviceClass.c_str(), info.c_str());
55
56 if (deviceClass == "primary") {
57 return GetId(HDI_ID_BASE_RENDER, HDI_ID_TYPE_PRIMARY, HDI_ID_INFO_DEFAULT);
58 } else if (deviceClass == "usb") {
59 return GetId(HDI_ID_BASE_RENDER, HDI_ID_TYPE_PRIMARY, HDI_ID_INFO_USB);
60 } else if (deviceClass == "dp") {
61 return GetId(HDI_ID_BASE_RENDER, HDI_ID_TYPE_PRIMARY, HDI_ID_INFO_DP);
62 } else if (deviceClass == "a2dp") {
63 return GetId(HDI_ID_BASE_RENDER, HDI_ID_TYPE_BLUETOOTH, HDI_ID_INFO_DEFAULT);
64 } else if (deviceClass == "a2dp_fast") {
65 return GetId(HDI_ID_BASE_RENDER, HDI_ID_TYPE_BLUETOOTH, HDI_ID_INFO_MMAP);
66 #ifdef FEATURE_FILE_IO
67 } else if (deviceClass == "file_io") {
68 return GetId(HDI_ID_BASE_RENDER, HDI_ID_TYPE_FILE, HDI_ID_INFO_DEFAULT);
69 #endif
70 #ifdef FEATURE_DISTRIBUTE_AUDIO
71 } else if (deviceClass == "remote") {
72 return GetId(HDI_ID_BASE_RENDER, HDI_ID_TYPE_REMOTE, info);
73 #endif
74 } else if (deviceClass == "offload") {
75 return GetId(HDI_ID_BASE_RENDER, HDI_ID_TYPE_OFFLOAD, HDI_ID_INFO_DEFAULT);
76 } else if (deviceClass == "multichannel") {
77 return GetId(HDI_ID_BASE_RENDER, HDI_ID_TYPE_MULTICHANNEL, HDI_ID_INFO_DEFAULT);
78 } else if (deviceClass == "primary_direct_voip") {
79 return GetId(HDI_ID_BASE_RENDER, HDI_ID_TYPE_PRIMARY, HDI_ID_INFO_VOIP);
80 } else if (deviceClass == "primary_mmap_voip") {
81 return GetId(HDI_ID_BASE_RENDER, HDI_ID_TYPE_FAST, HDI_ID_INFO_VOIP);
82 }
83
84 AUDIO_ERR_LOG("invalid param, deviceClass: %{public}s, info: %{public}s", deviceClass.c_str(), info.c_str());
85 return HDI_INVALID_ID;
86 }
87
GetCaptureIdByDeviceClass(const std::string & deviceClass,const SourceType sourceType,const std::string & info)88 uint32_t IdHandler::GetCaptureIdByDeviceClass(const std::string &deviceClass, const SourceType sourceType,
89 const std::string &info)
90 {
91 CHECK_AND_RETURN_RET_LOG(!deviceClass.empty(), HDI_INVALID_ID, "invalid device class");
92 AUDIO_INFO_LOG("deviceClass: %{public}s, sourceType: %{public}d, info: %{public}s", deviceClass.c_str(), sourceType,
93 info.c_str());
94
95 if (deviceClass == "primary") {
96 if (sourceType == SOURCE_TYPE_WAKEUP) {
97 return GetId(HDI_ID_BASE_CAPTURE, HDI_ID_TYPE_WAKEUP, info);
98 }
99 if (info == HDI_ID_INFO_EC || info == HDI_ID_INFO_MIC_REF) {
100 return GetId(HDI_ID_BASE_CAPTURE, HDI_ID_TYPE_PRIMARY, info);
101 }
102 return GetId(HDI_ID_BASE_CAPTURE, HDI_ID_TYPE_PRIMARY, HDI_ID_INFO_DEFAULT);
103 } else if (deviceClass == "usb") {
104 return GetId(HDI_ID_BASE_CAPTURE, HDI_ID_TYPE_PRIMARY, HDI_ID_INFO_USB);
105 } else if (deviceClass == "a2dp") {
106 return GetId(HDI_ID_BASE_CAPTURE, HDI_ID_TYPE_BLUETOOTH, HDI_ID_INFO_DEFAULT);
107 #ifdef FEATURE_FILE_IO
108 } else if (deviceClass == "file_io") {
109 return GetId(HDI_ID_BASE_CAPTURE, HDI_ID_TYPE_FILE, HDI_ID_INFO_DEFAULT);
110 #endif
111 #ifdef FEATURE_DISTRIBUTE_AUDIO
112 } else if (deviceClass == "remote") {
113 return GetId(HDI_ID_BASE_CAPTURE, HDI_ID_TYPE_REMOTE, info);
114 #endif
115 }
116
117 AUDIO_ERR_LOG("invalid param, deviceClass: %{public}s, sourceType: %{public}d, info: %{public}s",
118 deviceClass.c_str(), sourceType, info.c_str());
119 return HDI_INVALID_ID;
120 }
121
IncInfoIdUseCount(uint32_t id)122 void IdHandler::IncInfoIdUseCount(uint32_t id)
123 {
124 uint32_t infoId = id & HDI_ID_INFO_MASK;
125 CHECK_AND_RETURN_LOG(infoIdMap_.count(infoId) != 0, "invalid id %{public}u", id);
126 std::lock_guard<std::mutex> lock(infoIdMtx_);
127 infoIdMap_[infoId].useCount_++;
128 }
129
DecInfoIdUseCount(uint32_t id)130 void IdHandler::DecInfoIdUseCount(uint32_t id)
131 {
132 uint32_t infoId = id & HDI_ID_INFO_MASK;
133 CHECK_AND_RETURN_LOG(infoIdMap_.count(infoId) != 0, "invalid id %{public}u", id);
134 std::lock_guard<std::mutex> lock(infoIdMtx_);
135 if (infoIdMap_[infoId].useCount_.load() > 0) {
136 infoIdMap_[infoId].useCount_--;
137 if (infoIdMap_[infoId].useCount_.load() > 0) {
138 AUDIO_DEBUG_LOG("info: %{public}s, useCount: %{public}u", infoIdMap_[infoId].info_.c_str(),
139 infoIdMap_[infoId].useCount_.load());
140 return;
141 }
142 }
143 infoIdMap_.erase(infoId);
144 std::lock_guard<std::mutex> freeLock(freeInfoIdMtx_);
145 freeInfoIdSet_.emplace(infoId);
146 }
147
CheckId(uint32_t id,HdiIdBase requireBase)148 bool IdHandler::CheckId(uint32_t id, HdiIdBase requireBase)
149 {
150 CHECK_AND_RETURN_RET_LOG(ParseBase(id) == requireBase, false, "invalid id base, id: %{public}u, "
151 "requireBase: %{public}u", id, requireBase);
152 CHECK_AND_RETURN_RET_LOG(ParseType(id) < HDI_ID_TYPE_NUM, false, "invalid id type");
153 CHECK_AND_RETURN_RET_LOG(!ParseInfo(id).empty(), false, "invalid id info");
154 return true;
155 }
156
ParseBase(uint32_t id)157 uint32_t IdHandler::ParseBase(uint32_t id)
158 {
159 return (id & HDI_ID_BASE_MASK) >> HDI_ID_BASE_OFFSET;
160 }
161
ParseType(uint32_t id)162 uint32_t IdHandler::ParseType(uint32_t id)
163 {
164 return (id & HDI_ID_TYPE_MASK) >> HDI_ID_TYPE_OFFSET;
165 }
166
ParseInfo(uint32_t id)167 std::string IdHandler::ParseInfo(uint32_t id)
168 {
169 std::lock_guard<std::mutex> lock(infoIdMtx_);
170 uint32_t infoId = id & HDI_ID_INFO_MASK;
171 CHECK_AND_RETURN_RET_LOG(infoIdMap_.count(infoId) != 0, "", "invalid id %{public}u", id);
172 return infoIdMap_[infoId].info_;
173 }
174
CreateInfoId(void)175 uint32_t IdHandler::CreateInfoId(void)
176 {
177 if (freeInfoIdSet_.empty()) {
178 return infoIdMap_.size();
179 }
180 std::lock_guard<std::mutex> lock(freeInfoIdMtx_);
181 uint32_t infoId = *freeInfoIdSet_.begin();
182 freeInfoIdSet_.erase(infoId);
183 return infoId;
184 }
185
186 } // namespace AudioStandard
187 } // namespace OHOS
188