• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &params, 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 &params, 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 &params, 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