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_utils.h"
17 
18 #include <ctime>
19 
20 #include "daudio_constants.h"
21 #include "daudio_errcode.h"
22 #include "daudio_log.h"
23 
24 #undef DH_LOG_TAG
25 #define DH_LOG_TAG "DAudioUtils"
26 
27 namespace OHOS {
28 namespace DistributedHardware {
29 constexpr size_t INT32_SHORT_ID_LENGTH = 20;
30 constexpr size_t INT32_PLAINTEXT_LENGTH = 4;
31 constexpr size_t INT32_MIN_ID_LENGTH = 3;
32 constexpr uint8_t MAX_KEY_DH_ID_LEN = 20;
33 
GetAnonyString(const std::string & value)34 std::string GetAnonyString(const std::string &value)
35 {
36     std::string res;
37     std::string tmpStr("******");
38     size_t strLen = value.length();
39     if (strLen < INT32_MIN_ID_LENGTH) {
40         return tmpStr;
41     }
42 
43     if (strLen <= INT32_SHORT_ID_LENGTH) {
44         res += value[0];
45         res += tmpStr;
46         res += value[strLen - 1];
47     } else {
48         res.append(value, 0, INT32_PLAINTEXT_LENGTH);
49         res += tmpStr;
50         res.append(value, strLen - INT32_PLAINTEXT_LENGTH, INT32_PLAINTEXT_LENGTH);
51     }
52 
53     return res;
54 }
55 
GetChangeDevIdMap(int32_t devId)56 std::string GetChangeDevIdMap(int32_t devId)
57 {
58     std::string result = PRINT_NONE;
59     switch (devId) {
60         case DEFAULT_CAPTURE_ID:
61             result = PRINT_MIC;
62             break;
63         case LOW_LATENCY_RENDER_ID:
64             result = PRINT_SPK;
65             break;
66         case DEFAULT_RENDER_ID:
67             result = PRINT_SPK;
68             break;
69         default:
70             break;
71     }
72     return result;
73 }
74 
GetAudioParamStr(const std::string & params,const std::string & key,std::string & value)75 int32_t GetAudioParamStr(const std::string &params, const std::string &key, std::string &value)
76 {
77     size_t step = key.size();
78     if (step >= params.size()) {
79         return ERR_DH_AUDIO_HDF_FAIL;
80     }
81     size_t pos = params.find(key);
82     if (pos == params.npos || params.at(pos + step) != '=') {
83         return ERR_DH_AUDIO_COMMON_NOT_FOUND_KEY;
84     }
85     size_t splitPosEnd = params.find(';', pos);
86     if (splitPosEnd != params.npos) {
87         if (pos + step + 1 > splitPosEnd) {
88             return ERR_DH_AUDIO_HDF_FAIL;
89         }
90         value = params.substr(pos + step + 1, splitPosEnd - pos - step - 1);
91     } else {
92         value = params.substr(pos + step + 1);
93     }
94     return DH_SUCCESS;
95 }
96 
GetAudioParamInt(const std::string & params,const std::string & key,int32_t & value)97 int32_t GetAudioParamInt(const std::string &params, const std::string &key, int32_t &value)
98 {
99     std::string val = "-1";
100     int32_t ret = GetAudioParamStr(params, key, val);
101     if (!CheckIsNum(val)) {
102         DHLOGE("String is not number. str:%{public}s.", val.c_str());
103         return -1;
104     }
105     value = std::atoi(val.c_str());
106     return ret;
107 }
108 
CheckIsNum(const std::string & jsonString)109 bool CheckIsNum(const std::string &jsonString)
110 {
111     if (jsonString.empty() || jsonString.size() > MAX_KEY_DH_ID_LEN) {
112         DHLOGE("Json string size is zero or too long.");
113         return false;
114     }
115     for (char const &c : jsonString) {
116         if (!std::isdigit(c)) {
117             DHLOGE("Json string is not number.");
118             return false;
119         }
120     }
121     return true;
122 }
123 
GetAudioParamUInt(const std::string & params,const std::string & key,uint32_t & value)124 int32_t GetAudioParamUInt(const std::string &params, const std::string &key, uint32_t &value)
125 {
126     value = 0;
127     return DH_SUCCESS;
128 }
129 
GetAudioParamBool(const std::string & params,const std::string & key,bool & value)130 int32_t GetAudioParamBool(const std::string &params, const std::string &key, bool &value)
131 {
132     std::string val;
133     GetAudioParamStr(params, key, val);
134     value = (val != "0");
135     return DH_SUCCESS;
136 }
137 
SetAudioParamStr(std::string & params,const std::string & key,const std::string & value)138 int32_t SetAudioParamStr(std::string &params, const std::string &key, const std::string &value)
139 {
140     params = params + key + '=' + value + ';';
141     return DH_SUCCESS;
142 }
143 
GetDevTypeByDHId(int32_t dhId)144 int32_t GetDevTypeByDHId(int32_t dhId)
145 {
146     if (static_cast<uint32_t>(dhId) & 0x8000000) {
147         return AUDIO_DEVICE_TYPE_MIC;
148     } else if (static_cast<uint32_t>(dhId) & 0x7ffffff) {
149         return AUDIO_DEVICE_TYPE_SPEAKER;
150     }
151     return AUDIO_DEVICE_TYPE_UNKNOWN;
152 }
153 
GetNowTimeUs()154 int64_t GetNowTimeUs()
155 {
156     std::chrono::microseconds nowUs =
157         std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch());
158     return nowUs.count();
159 }
160 
CalculateFrameSize(uint32_t sampleRate,uint32_t channelCount,int32_t format,uint32_t timeInterval,bool isMMAP)161 uint32_t CalculateFrameSize(uint32_t sampleRate, uint32_t channelCount,
162     int32_t format, uint32_t timeInterval, bool isMMAP)
163 {
164     return isMMAP ? (sampleRate * channelCount * static_cast<uint32_t>(format) * timeInterval) /
165                      AUDIO_MS_PER_SECOND : DEFAULT_AUDIO_DATA_SIZE;
166 }
167 
CalculateSampleNum(uint32_t sampleRate,uint32_t timems)168 int32_t CalculateSampleNum(uint32_t sampleRate, uint32_t timems)
169 {
170     return (sampleRate * timems) / AUDIO_MS_PER_SECOND;
171 }
172 
GetCurNano()173 int64_t GetCurNano()
174 {
175     int64_t result = -1;
176     struct timespec time;
177     clockid_t clockId = CLOCK_MONOTONIC;
178     int ret = clock_gettime(clockId, &time);
179     if (ret < 0) {
180         return result;
181     }
182     result = (time.tv_sec * AUDIO_NS_PER_SECOND) + time.tv_nsec;
183     return result;
184 }
185 
AbsoluteSleep(int64_t nanoTime)186 int32_t AbsoluteSleep(int64_t nanoTime)
187 {
188     int32_t ret = -1;
189     if (nanoTime <= 0) {
190         return ret;
191     }
192     struct timespec time;
193     time.tv_sec = nanoTime / AUDIO_NS_PER_SECOND;
194     time.tv_nsec = nanoTime - (time.tv_sec * AUDIO_NS_PER_SECOND);
195 
196     clockid_t clockId = CLOCK_MONOTONIC;
197     ret = clock_nanosleep(clockId, TIMER_ABSTIME, &time, nullptr);
198     return ret;
199 }
200 
CalculateOffset(const int64_t frameIndex,const int64_t framePeriodNs,const int64_t startTime)201 int64_t CalculateOffset(const int64_t frameIndex, const int64_t framePeriodNs, const int64_t startTime)
202 {
203     int64_t totalOffset = GetCurNano() - startTime;
204     return totalOffset - frameIndex * framePeriodNs;
205 }
206 
UpdateTimeOffset(const int64_t frameIndex,const int64_t framePeriodNs,int64_t & startTime)207 int64_t UpdateTimeOffset(const int64_t frameIndex, const int64_t framePeriodNs, int64_t &startTime)
208 {
209     int64_t timeOffset = 0;
210     if (frameIndex == 0) {
211         startTime = GetCurNano();
212     } else if (frameIndex % AUDIO_OFFSET_FRAME_NUM == 0) {
213         timeOffset = CalculateOffset(frameIndex, framePeriodNs, startTime);
214     }
215     return timeOffset;
216 }
217 
IsOutDurationRange(int64_t startTime,int64_t endTime,int64_t lastStartTime)218 bool IsOutDurationRange(int64_t startTime, int64_t endTime, int64_t lastStartTime)
219 {
220     int64_t currentInterval = endTime - startTime;
221     int64_t twiceInterval = startTime - lastStartTime;
222     return (currentInterval > MAX_TIME_INTERVAL_US || twiceInterval > MAX_TIME_INTERVAL_US) ? true : false;
223 }
224 
SaveFile(const std::string fileName,uint8_t * audioData,int32_t size)225 void SaveFile(const std::string fileName, uint8_t *audioData, int32_t size)
226 {
227     char path[PATH_MAX + 1] = {0x00};
228     if (fileName.length() > PATH_MAX || realpath(fileName.c_str(), path) == nullptr) {
229         DHLOGE("The file path is invalid.");
230         return;
231     }
232     std::ofstream ofs(path, std::ios::binary | std::ios::out | std::ios::app);
233     if (!ofs.is_open()) {
234         return;
235     }
236     ofs.write(reinterpret_cast<char *>(audioData), size);
237     ofs.close();
238 }
239 
WrapCJsonItem(const std::initializer_list<std::pair<std::string,std::string>> & keys,std::string & content)240 int32_t WrapCJsonItem(const std::initializer_list<std::pair<std::string, std::string>> &keys, std::string &content)
241 {
242     cJSON *jParam = cJSON_CreateObject();
243     if (jParam == nullptr) {
244         return ERR_DH_AUDIO_HDF_FAIL;
245     }
246     for (auto item : keys) {
247         cJSON_AddStringToObject(jParam, item.first.c_str(), item.second.c_str());
248     }
249     char *jsonData = cJSON_PrintUnformatted(jParam);
250     if (jsonData == nullptr) {
251         cJSON_Delete(jParam);
252         return ERR_DH_AUDIO_HDF_FAIL;
253     }
254     content = std::string(jsonData);
255     cJSON_Delete(jParam);
256     cJSON_free(jsonData);
257     return DH_SUCCESS;
258 }
259 
CJsonParamCheck(const cJSON * jsonObj,const std::initializer_list<std::string> & keys)260 bool CJsonParamCheck(const cJSON *jsonObj, const std::initializer_list<std::string> &keys)
261 {
262     if (jsonObj == nullptr || !cJSON_IsObject(jsonObj)) {
263         DHLOGE("JSON parameter is invalid.");
264         return false;
265     }
266 
267     for (auto it = keys.begin(); it != keys.end(); it++) {
268         cJSON *paramValue = cJSON_GetObjectItemCaseSensitive(jsonObj, (*it).c_str());
269         if (paramValue == nullptr) {
270             DHLOGE("JSON parameter does not contain key: %{public}s", (*it).c_str());
271             return false;
272         }
273     }
274     return true;
275 }
276 
ParseStringFromArgs(const std::string & args,const char * key)277 std::string ParseStringFromArgs(const std::string &args, const char *key)
278 {
279     DHLOGD("ParseStringFrom Args : %{public}s", args.c_str());
280     cJSON *jParam = cJSON_Parse(args.c_str());
281     if (jParam == nullptr) {
282         DHLOGE("Failed to parse JSON: %{public}s", cJSON_GetErrorPtr());
283         cJSON_Delete(jParam);
284         return "Failed to parse JSON";
285     }
286     if (!CJsonParamCheck(jParam, { key })) {
287         DHLOGE("Not found the key : %{public}s.", key);
288         cJSON_Delete(jParam);
289         return "Not found the key.";
290     }
291     cJSON *dhIdItem = cJSON_GetObjectItem(jParam, key);
292     if (dhIdItem == NULL || !cJSON_IsString(dhIdItem)) {
293         DHLOGE("Not found the value of the key : %{public}s.", key);
294         cJSON_Delete(jParam);
295         return "Not found the value.";
296     }
297     std::string content(dhIdItem->valuestring);
298     cJSON_Delete(jParam);
299     DHLOGD("Parsed string is: %{public}s.", content.c_str());
300     return content;
301 }
302 } // namespace DistributedHardware
303 } // namespace OHOS