1 /*
2 * Copyright (c) 2022-2023 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_util.h"
17
18 #include <ctime>
19 #include <cstddef>
20 #include <iomanip>
21 #include <map>
22 #include <random>
23 #include <sstream>
24 #include <sys/time.h>
25
26 #include "softbus_bus_center.h"
27
28 #include "daudio_constants.h"
29 #include "daudio_errorcode.h"
30 #include "daudio_log.h"
31 #include "parameter.h"
32
33 #undef DH_LOG_TAG
34 #define DH_LOG_TAG "DAudioUtils"
35
36 namespace OHOS {
37 namespace DistributedHardware {
38 using JsonTypeCheckFunc = bool (*)(const json &jsonObj, const std::string &key);
39 constexpr int32_t WORD_WIDTH_8 = 8;
40 constexpr int32_t WORD_WIDTH_4 = 4;
41 constexpr size_t INT32_SHORT_ID_LENGTH = 20;
42 constexpr size_t INT32_MIN_ID_LENGTH = 3;
43 constexpr size_t INT32_PLAINTEXT_LENGTH = 4;
44 constexpr uint8_t MAX_KEY_DH_ID_LEN = 20;
45
46 std::map<std::string, JsonTypeCheckFunc> typeCheckMap = {
47 std::map<std::string, JsonTypeCheckFunc>::value_type(KEY_TYPE, &DistributedHardware::IsInt32),
48 std::map<std::string, JsonTypeCheckFunc>::value_type(KEY_EVENT_CONTENT, &DistributedHardware::IsString),
49 std::map<std::string, JsonTypeCheckFunc>::value_type(KEY_DH_ID, &DistributedHardware::IsString),
50 std::map<std::string, JsonTypeCheckFunc>::value_type(KEY_DEV_ID, &DistributedHardware::IsString),
51 std::map<std::string, JsonTypeCheckFunc>::value_type(KEY_RESULT, &DistributedHardware::IsInt32),
52 std::map<std::string, JsonTypeCheckFunc>::value_type(KEY_EVENT_TYPE, &DistributedHardware::IsInt32),
53 std::map<std::string, JsonTypeCheckFunc>::value_type(KEY_AUDIO_PARAM, &DistributedHardware::IsAudioParam),
54 std::map<std::string, JsonTypeCheckFunc>::value_type(KEY_ATTRS, &DistributedHardware::IsString),
55 std::map<std::string, JsonTypeCheckFunc>::value_type(KEY_RANDOM_TASK_CODE, &DistributedHardware::IsString),
56 std::map<std::string, JsonTypeCheckFunc>::value_type(KEY_SAMPLING_RATE, &DistributedHardware::IsInt32),
57 std::map<std::string, JsonTypeCheckFunc>::value_type(KEY_CHANNELS, &DistributedHardware::IsInt32),
58 std::map<std::string, JsonTypeCheckFunc>::value_type(KEY_FORMAT, &DistributedHardware::IsInt32),
59 std::map<std::string, JsonTypeCheckFunc>::value_type(KEY_SOURCE_TYPE, &DistributedHardware::IsInt32),
60 std::map<std::string, JsonTypeCheckFunc>::value_type(KEY_CONTENT_TYPE, &DistributedHardware::IsInt32),
61 std::map<std::string, JsonTypeCheckFunc>::value_type(KEY_STREAM_USAGE, &DistributedHardware::IsInt32),
62 };
63
GetLocalDeviceNetworkId(std::string & networkId)64 int32_t GetLocalDeviceNetworkId(std::string &networkId)
65 {
66 NodeBasicInfo basicInfo = { { 0 } };
67 int32_t ret = GetLocalNodeDeviceInfo(PKG_NAME.c_str(), &basicInfo);
68 if (ret != DH_SUCCESS) {
69 DHLOGE("Failed to obtain the network ID of the local device. ret: %d", ret);
70 return ret;
71 }
72
73 networkId = std::string(basicInfo.networkId);
74 return DH_SUCCESS;
75 }
76
GetRandomID()77 std::string GetRandomID()
78 {
79 static std::random_device rd;
80 static std::uniform_int_distribution<uint64_t> dist(0ULL, 0xFFFFFFFFFFFFFFFFULL);
81 uint64_t ab = dist(rd);
82 uint64_t cd = dist(rd);
83 uint32_t a, b, c, d;
84 std::stringstream ss;
85 ab = (ab & 0xFFFFFFFFFFFF0FFFULL) | 0x0000000000004000ULL;
86 cd = (cd & 0x3FFFFFFFFFFFFFFFULL) | 0x8000000000000000ULL;
87 a = (ab >> 32U);
88 b = (ab & 0xFFFFFFFFU);
89 c = (cd >> 32U);
90 d = (cd & 0xFFFFFFFFU);
91 ss << std::hex << std::nouppercase << std::setfill('0');
92 ss << std::setw(WORD_WIDTH_8) << (a);
93 ss << std::setw(WORD_WIDTH_4) << (b >> 16U);
94 ss << std::setw(WORD_WIDTH_4) << (b & 0xFFFFU);
95 ss << std::setw(WORD_WIDTH_4) << (c >> 16U);
96 ss << std::setw(WORD_WIDTH_4) << (c & 0xFFFFU);
97 ss << std::setw(WORD_WIDTH_8) << d;
98
99 return ss.str();
100 }
101
GetAnonyString(const std::string & value)102 std::string GetAnonyString(const std::string &value)
103 {
104 std::string res;
105 std::string tmpStr("******");
106 size_t strLen = value.length();
107 if (strLen < INT32_MIN_ID_LENGTH) {
108 return tmpStr;
109 }
110
111 if (strLen <= INT32_SHORT_ID_LENGTH) {
112 res += value[0];
113 res += tmpStr;
114 res += value[strLen - 1];
115 } else {
116 res.append(value, 0, INT32_PLAINTEXT_LENGTH);
117 res += tmpStr;
118 res.append(value, strLen - INT32_PLAINTEXT_LENGTH, INT32_PLAINTEXT_LENGTH);
119 }
120
121 return res;
122 }
123
GetDevTypeByDHId(int32_t dhId)124 int32_t GetDevTypeByDHId(int32_t dhId)
125 {
126 if (static_cast<uint32_t>(dhId) & 0x8000000) {
127 return AUDIO_DEVICE_TYPE_MIC;
128 } else if (static_cast<uint32_t>(dhId) & 0x7ffffff) {
129 return AUDIO_DEVICE_TYPE_SPEAKER;
130 }
131 return AUDIO_DEVICE_TYPE_UNKNOWN;
132 }
133
GetCurrentTime(int64_t & tvSec,int64_t & tvNSec)134 void GetCurrentTime(int64_t &tvSec, int64_t &tvNSec)
135 {
136 struct timespec time;
137 if (clock_gettime(CLOCK_MONOTONIC, &time) < 0) {
138 DHLOGE("Get current time failed");
139 }
140 tvSec = time.tv_sec;
141 tvNSec = time.tv_nsec;
142 }
143
GetNowTimeUs()144 int64_t GetNowTimeUs()
145 {
146 std::chrono::microseconds nowUs =
147 std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch());
148 return nowUs.count();
149 }
150
GetAudioParamStr(const std::string & params,const std::string & key,std::string & value)151 int32_t GetAudioParamStr(const std::string ¶ms, const std::string &key, std::string &value)
152 {
153 size_t step = key.size();
154 if (step >= params.size()) {
155 return ERR_DH_AUDIO_FAILED;
156 }
157 size_t pos = params.find(key);
158 if (pos == params.npos || params.at(pos + step) != '=') {
159 return ERR_DH_AUDIO_NOT_FOUND_KEY;
160 }
161 size_t splitPosEnd = params.find(';', pos);
162 if (splitPosEnd != params.npos) {
163 value = params.substr(pos + step + 1, splitPosEnd - pos - step - 1);
164 } else {
165 value = params.substr(pos + step + 1);
166 }
167 return DH_SUCCESS;
168 }
169
GetAudioParamBool(const std::string & params,const std::string & key,bool & value)170 int32_t GetAudioParamBool(const std::string ¶ms, const std::string &key, bool &value)
171 {
172 std::string val;
173 int32_t ret = GetAudioParamStr(params, key, val);
174 if (ret != DH_SUCCESS) {
175 DHLOGE("Get audio param string fail, error code %d.", ret);
176 return ret;
177 }
178
179 value = (val != "0");
180 return DH_SUCCESS;
181 }
182
GetAudioParamInt(const std::string & params,const std::string & key,int32_t & value)183 int32_t GetAudioParamInt(const std::string ¶ms, const std::string &key, int32_t &value)
184 {
185 std::string val = "0";
186 int32_t ret = GetAudioParamStr(params, key, val);
187 if (ret != DH_SUCCESS) {
188 DHLOGE("Get audio param string fail, error code %d.", ret);
189 return ret;
190 }
191
192 value = std::stoi(val);
193 return DH_SUCCESS;
194 }
195
JsonParamCheck(const json & jsonObj,const std::initializer_list<std::string> & keys)196 bool JsonParamCheck(const json &jsonObj, const std::initializer_list<std::string> &keys)
197 {
198 if (jsonObj.is_discarded()) {
199 DHLOGE("Json parameter is invalid.");
200 return false;
201 }
202
203 for (auto it = keys.begin(); it != keys.end(); it++) {
204 if (!jsonObj.contains(*it)) {
205 DHLOGE("Json parameter not contain param(%s).", (*it).c_str());
206 return false;
207 }
208
209 auto iter = typeCheckMap.find(*it);
210 if (iter == typeCheckMap.end()) {
211 DHLOGE("Check is not supported yet, key %s.", (*it).c_str());
212 return false;
213 }
214 JsonTypeCheckFunc &func = iter->second;
215 bool res = (*func)(jsonObj, *it);
216 if (!res) {
217 DHLOGE("The key %s value format in json is illegal.", (*it).c_str());
218 return false;
219 }
220 }
221 return true;
222 }
223
IsString(const json & jsonObj,const std::string & key)224 bool IsString(const json &jsonObj, const std::string &key)
225 {
226 return jsonObj[key].is_string();
227 }
228
IsInt32(const json & jsonObj,const std::string & key)229 bool IsInt32(const json &jsonObj, const std::string &key)
230 {
231 return jsonObj[key].is_number_integer() && INT32_MIN <= jsonObj[key] && jsonObj[key] <= INT32_MAX;
232 }
233
IsAudioParam(const json & jsonObj,const std::string & key)234 bool IsAudioParam(const json &jsonObj, const std::string &key)
235 {
236 return JsonParamCheck(jsonObj[key],
237 { KEY_SAMPLING_RATE, KEY_CHANNELS, KEY_FORMAT, KEY_SOURCE_TYPE, KEY_CONTENT_TYPE, KEY_STREAM_USAGE });
238 }
239
CalculateSampleNum(uint32_t sampleRate,uint32_t timems)240 int32_t CalculateSampleNum(uint32_t sampleRate, uint32_t timems)
241 {
242 return (sampleRate * timems) / AUDIO_MS_PER_SECOND;
243 }
244
GetCurNano()245 int64_t GetCurNano()
246 {
247 int64_t result = -1;
248 struct timespec time;
249 clockid_t clockId = CLOCK_MONOTONIC;
250 int ret = clock_gettime(clockId, &time);
251 if (ret < 0) {
252 DHLOGE("GetCurNanoTime fail, ret: %d", ret);
253 return result;
254 }
255 result = (time.tv_sec * AUDIO_NS_PER_SECOND) + time.tv_nsec;
256 return result;
257 }
258
AbsoluteSleep(int64_t nanoTime)259 int32_t AbsoluteSleep(int64_t nanoTime)
260 {
261 int32_t ret = -1;
262 if (nanoTime <= 0) {
263 DHLOGE("AbsoluteSleep invalid sleep time : %d ns", nanoTime);
264 return ret;
265 }
266 struct timespec time;
267 time.tv_sec = nanoTime / AUDIO_NS_PER_SECOND;
268 time.tv_nsec = nanoTime - (time.tv_sec * AUDIO_NS_PER_SECOND);
269
270 clockid_t clockId = CLOCK_MONOTONIC;
271 ret = clock_nanosleep(clockId, TIMER_ABSTIME, &time, nullptr);
272 if (ret != 0) {
273 DHLOGE("AbsoluteSleep may failed, ret is : %d", ret);
274 }
275 return ret;
276 }
277
CalculateOffset(const int64_t frameIndex,const int64_t framePeriodNs,const int64_t startTime)278 int64_t CalculateOffset(const int64_t frameIndex, const int64_t framePeriodNs, const int64_t startTime)
279 {
280 int64_t totalOffset = GetCurNano() - startTime;
281 return totalOffset - frameIndex * framePeriodNs;
282 }
283
UpdateTimeOffset(const int64_t frameIndex,const int64_t framePeriodNs,int64_t & startTime)284 int64_t UpdateTimeOffset(const int64_t frameIndex, const int64_t framePeriodNs, int64_t &startTime)
285 {
286 int64_t timeOffset = 0;
287 if (frameIndex == 0) {
288 startTime = GetCurNano();
289 } else if (frameIndex % AUDIO_OFFSET_FRAME_NUM == 0) {
290 timeOffset = CalculateOffset(frameIndex, framePeriodNs, startTime);
291 }
292 return timeOffset;
293 }
294
CheckIsNum(const std::string & jsonString)295 bool CheckIsNum(const std::string &jsonString)
296 {
297 if (jsonString.empty() || jsonString.size() > MAX_KEY_DH_ID_LEN) {
298 DHLOGE("Json string size %d, is zero or too long.", jsonString.size());
299 return false;
300 }
301 for (char const &c : jsonString) {
302 if (!std::isdigit(c)) {
303 DHLOGE("Json string is not number.");
304 return false;
305 }
306 }
307 return true;
308 }
309
CheckDevIdIsLegal(const std::string & devId)310 bool CheckDevIdIsLegal(const std::string &devId)
311 {
312 if (devId.empty() || devId.size() > DAUDIO_MAX_DEVICE_ID_LEN) {
313 DHLOGE("DevId size %d, is zero or too long.", devId.size());
314 return false;
315 }
316 for (char const &c : devId) {
317 if (!std::isalnum(c)) {
318 DHLOGE("DevId is not number or letter.");
319 return false;
320 }
321 }
322 return true;
323 }
324
325 template <typename T>
GetSysPara(const char * key,T & value)326 bool GetSysPara(const char *key, T &value)
327 {
328 if (key == nullptr) {
329 DHLOGE("GetSysPara: key is nullptr");
330 return false;
331 }
332 char paraValue[20] = {0}; // 20 for system parameter
333 auto res = GetParameter(key, "-1", paraValue, sizeof(paraValue));
334 if (res <= 0) {
335 DHLOGD("GetSysPara fail, key:%{public}s res:%{public}d", key, res);
336 return false;
337 }
338 DHLOGI("GetSysPara: key:%{public}s value:%{public}s", key, paraValue);
339 std::stringstream valueStr;
340 valueStr << paraValue;
341 valueStr >> value;
342 return true;
343 }
344
345 template bool GetSysPara(const char *key, int32_t &value);
346 template bool GetSysPara(const char *key, uint32_t &value);
347 template bool GetSysPara(const char *key, int64_t &value);
348 template bool GetSysPara(const char *key, std::string &value);
349
IsParamEnabled(const std::string & key,bool & isEnabled)350 bool IsParamEnabled(const std::string &key, bool &isEnabled)
351 {
352 // by default: old trans
353 int32_t policyFlag = 0;
354 if (GetSysPara(key.c_str(), policyFlag) && policyFlag == 1) {
355 isEnabled = true;
356 return true;
357 }
358 isEnabled = false;
359 return false;
360 }
361 } // namespace DistributedHardware
362 } // namespace OHOS