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
55 if (deviceClass == "primary") {
56 return GetId(HDI_ID_BASE_RENDER, HDI_ID_TYPE_PRIMARY, HDI_ID_INFO_DEFAULT);
57 } else if (deviceClass == "usb") {
58 return GetId(HDI_ID_BASE_RENDER, HDI_ID_TYPE_PRIMARY, HDI_ID_INFO_USB);
59 } else if (deviceClass == "dp") {
60 return GetId(HDI_ID_BASE_RENDER, HDI_ID_TYPE_PRIMARY, HDI_ID_INFO_DP);
61 } else if (deviceClass == "a2dp") {
62 return GetId(HDI_ID_BASE_RENDER, HDI_ID_TYPE_BLUETOOTH, HDI_ID_INFO_DEFAULT);
63 } else if (deviceClass == "a2dp_fast") {
64 return GetId(HDI_ID_BASE_RENDER, HDI_ID_TYPE_BLUETOOTH, HDI_ID_INFO_MMAP);
65 } else if (deviceClass == "hearing_aid") {
66 return GetId(HDI_ID_BASE_RENDER, HDI_ID_TYPE_BLUETOOTH, HDI_ID_INFO_HEARING_AID);
67 #ifdef FEATURE_FILE_IO
68 } else if (deviceClass == "file_io") {
69 return GetId(HDI_ID_BASE_RENDER, HDI_ID_TYPE_FILE, HDI_ID_INFO_DEFAULT);
70 #endif
71 #ifdef FEATURE_DISTRIBUTE_AUDIO
72 } else if (deviceClass == "remote") {
73 return GetId(HDI_ID_BASE_RENDER, HDI_ID_TYPE_REMOTE, info);
74 } else if (deviceClass == "remote_offload") {
75 return GetId(HDI_ID_BASE_RENDER, HDI_ID_TYPE_REMOTE_OFFLOAD, info);
76 #endif
77 } else if (deviceClass == "offload") {
78 return GetId(HDI_ID_BASE_RENDER, HDI_ID_TYPE_OFFLOAD, HDI_ID_INFO_DEFAULT);
79 } else if (deviceClass == "multichannel") {
80 return GetId(HDI_ID_BASE_RENDER, HDI_ID_TYPE_MULTICHANNEL, HDI_ID_INFO_DEFAULT);
81 } else if (deviceClass == "dp_multichannel") {
82 return GetId(HDI_ID_BASE_RENDER, HDI_ID_TYPE_MULTICHANNEL, HDI_ID_INFO_DP);
83 } else if (deviceClass == "primary_direct_voip") {
84 return GetId(HDI_ID_BASE_RENDER, HDI_ID_TYPE_PRIMARY, HDI_ID_INFO_VOIP);
85 } else if (deviceClass == "primary_mmap_voip") {
86 return GetId(HDI_ID_BASE_RENDER, HDI_ID_TYPE_FAST, HDI_ID_INFO_VOIP);
87 }
88
89 AUDIO_ERR_LOG("invalid param, deviceClass: %{public}s, info: %{public}s", deviceClass.c_str(), info.c_str());
90 return HDI_INVALID_ID;
91 }
92
GetCaptureIdByDeviceClass(const std::string & deviceClass,const SourceType sourceType,const std::string & info)93 uint32_t IdHandler::GetCaptureIdByDeviceClass(const std::string &deviceClass, const SourceType sourceType,
94 const std::string &info)
95 {
96 CHECK_AND_RETURN_RET_LOG(!deviceClass.empty(), HDI_INVALID_ID, "invalid device class");
97 AUDIO_INFO_LOG("deviceClass: %{public}s, sourceType: %{public}d, info: %{public}s", deviceClass.c_str(), sourceType,
98 info.c_str());
99
100 if (deviceClass == "primary") {
101 if (sourceType == SOURCE_TYPE_WAKEUP) {
102 return GetId(HDI_ID_BASE_CAPTURE, HDI_ID_TYPE_WAKEUP, info);
103 }
104 if (info == HDI_ID_INFO_EC || info == HDI_ID_INFO_MIC_REF) {
105 return GetId(HDI_ID_BASE_CAPTURE, HDI_ID_TYPE_PRIMARY, info);
106 }
107 return GetId(HDI_ID_BASE_CAPTURE, HDI_ID_TYPE_PRIMARY, HDI_ID_INFO_DEFAULT);
108 } else if (deviceClass == "usb") {
109 return GetId(HDI_ID_BASE_CAPTURE, HDI_ID_TYPE_PRIMARY, HDI_ID_INFO_USB);
110 } else if (deviceClass == "a2dp") {
111 return GetId(HDI_ID_BASE_CAPTURE, HDI_ID_TYPE_BLUETOOTH, HDI_ID_INFO_DEFAULT);
112 #ifdef FEATURE_FILE_IO
113 } else if (deviceClass == "file_io") {
114 return GetId(HDI_ID_BASE_CAPTURE, HDI_ID_TYPE_FILE, HDI_ID_INFO_DEFAULT);
115 #endif
116 #ifdef FEATURE_DISTRIBUTE_AUDIO
117 } else if (deviceClass == "remote") {
118 return GetId(HDI_ID_BASE_CAPTURE, HDI_ID_TYPE_REMOTE, info);
119 #endif
120 } else if (deviceClass == "accessory") {
121 return GetId(HDI_ID_BASE_CAPTURE, HDI_ID_TYPE_ACCESSORY, HDI_ID_INFO_ACCESSORY);
122 }
123
124 AUDIO_ERR_LOG("invalid param, deviceClass: %{public}s, sourceType: %{public}d, info: %{public}s",
125 deviceClass.c_str(), sourceType, info.c_str());
126 return HDI_INVALID_ID;
127 }
128
IncInfoIdUseCount(uint32_t id)129 void IdHandler::IncInfoIdUseCount(uint32_t id)
130 {
131 uint32_t infoId = id & HDI_ID_INFO_MASK;
132 std::lock_guard<std::mutex> lock(infoIdMtx_);
133 CHECK_AND_RETURN_LOG(infoIdMap_.count(infoId) != 0, "invalid id %{public}u", id);
134 infoIdMap_[infoId].useCount_++;
135 AUDIO_DEBUG_LOG("info: %{public}s, useCount: %{public}u", infoIdMap_[infoId].info_.c_str(),
136 infoIdMap_[infoId].useCount_.load());
137 }
138
DecInfoIdUseCount(uint32_t id)139 void IdHandler::DecInfoIdUseCount(uint32_t id)
140 {
141 uint32_t infoId = id & HDI_ID_INFO_MASK;
142 std::lock_guard<std::mutex> lock(infoIdMtx_);
143 CHECK_AND_RETURN_LOG(infoIdMap_.count(infoId) != 0, "invalid id %{public}u", id);
144 if (infoIdMap_[infoId].useCount_.load() > 0) {
145 infoIdMap_[infoId].useCount_--;
146 AUDIO_DEBUG_LOG("info: %{public}s, useCount: %{public}u", infoIdMap_[infoId].info_.c_str(),
147 infoIdMap_[infoId].useCount_.load());
148 if (infoIdMap_[infoId].useCount_.load() > 0) {
149 return;
150 }
151 }
152 infoIdMap_.erase(infoId);
153 std::lock_guard<std::mutex> freeLock(freeInfoIdMtx_);
154 freeInfoIdSet_.emplace(infoId);
155 }
156
CheckId(uint32_t id,HdiIdBase requireBase)157 bool IdHandler::CheckId(uint32_t id, HdiIdBase requireBase)
158 {
159 CHECK_AND_RETURN_RET_LOG(ParseBase(id) == requireBase, false, "invalid id base, id: %{public}u, "
160 "requireBase: %{public}u", id, requireBase);
161 CHECK_AND_RETURN_RET_LOG(ParseType(id) < HDI_ID_TYPE_NUM, false, "invalid id type");
162 CHECK_AND_RETURN_RET_LOG(!ParseInfo(id).empty(), false, "invalid id info");
163 return true;
164 }
165
ParseBase(uint32_t id)166 uint32_t IdHandler::ParseBase(uint32_t id)
167 {
168 return (id & HDI_ID_BASE_MASK) >> HDI_ID_BASE_OFFSET;
169 }
170
ParseType(uint32_t id)171 uint32_t IdHandler::ParseType(uint32_t id)
172 {
173 return (id & HDI_ID_TYPE_MASK) >> HDI_ID_TYPE_OFFSET;
174 }
175
ParseInfo(uint32_t id)176 std::string IdHandler::ParseInfo(uint32_t id)
177 {
178 std::lock_guard<std::mutex> lock(infoIdMtx_);
179 uint32_t infoId = id & HDI_ID_INFO_MASK;
180 CHECK_AND_RETURN_RET_LOG(infoIdMap_.count(infoId) != 0, "", "invalid id %{public}u", id);
181 return infoIdMap_[infoId].info_;
182 }
183
CreateInfoId(void)184 uint32_t IdHandler::CreateInfoId(void)
185 {
186 std::lock_guard<std::mutex> lock(freeInfoIdMtx_);
187
188 if (freeInfoIdSet_.empty()) {
189 return infoIdMap_.size();
190 }
191
192 uint32_t infoId = *freeInfoIdSet_.begin();
193 freeInfoIdSet_.erase(infoId);
194 return infoId;
195 }
196
197 } // namespace AudioStandard
198 } // namespace OHOS
199