• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 <cinttypes>
17 #include <ctime>
18 #include <sstream>
19 #include <ostream>
20 #include "audio_utils.h"
21 #include "audio_utils_c.h"
22 #include "audio_errors.h"
23 #include "audio_log.h"
24 #ifdef FEATURE_HITRACE_METER
25 #include "hitrace_meter.h"
26 #endif
27 #include "parameter.h"
28 #include "tokenid_kit.h"
29 #include "ipc_skeleton.h"
30 #include "access_token.h"
31 #include "accesstoken_kit.h"
32 #include "xcollie/xcollie.h"
33 #include "xcollie/xcollie_define.h"
34 
35 using OHOS::Security::AccessToken::AccessTokenKit;
36 
37 namespace OHOS {
38 namespace AudioStandard {
GetCurNano()39 int64_t ClockTime::GetCurNano()
40 {
41     int64_t result = -1; // -1 for bad result.
42     struct timespec time;
43     clockid_t clockId = CLOCK_MONOTONIC;
44     int ret = clock_gettime(clockId, &time);
45     CHECK_AND_RETURN_RET_LOG(ret >= 0, result,
46         "GetCurNanoTime fail, result:%{public}d", ret);
47     result = (time.tv_sec * AUDIO_NS_PER_SECOND) + time.tv_nsec;
48     return result;
49 }
50 
AbsoluteSleep(int64_t nanoTime)51 int32_t ClockTime::AbsoluteSleep(int64_t nanoTime)
52 {
53     int32_t ret = -1; // -1 for bad result.
54     CHECK_AND_RETURN_RET_LOG(nanoTime > 0, ret,
55         "AbsoluteSleep invalid sleep time :%{public}" PRId64 " ns", nanoTime);
56     struct timespec time;
57     time.tv_sec = nanoTime / AUDIO_NS_PER_SECOND;
58     time.tv_nsec = nanoTime - (time.tv_sec * AUDIO_NS_PER_SECOND); // Avoids % operation.
59 
60     clockid_t clockId = CLOCK_MONOTONIC;
61     ret = clock_nanosleep(clockId, TIMER_ABSTIME, &time, nullptr);
62     if (ret != 0) {
63         AUDIO_WARNING_LOG("AbsoluteSleep may failed, ret is :%{public}d", ret);
64     }
65 
66     return ret;
67 }
68 
RelativeSleep(int64_t nanoTime)69 int32_t ClockTime::RelativeSleep(int64_t nanoTime)
70 {
71     int32_t ret = -1; // -1 for bad result.
72     CHECK_AND_RETURN_RET_LOG(nanoTime > 0, ret,
73         "AbsoluteSleep invalid sleep time :%{public}" PRId64 " ns", nanoTime);
74     struct timespec time;
75     time.tv_sec = nanoTime / AUDIO_NS_PER_SECOND;
76     time.tv_nsec = nanoTime - (time.tv_sec * AUDIO_NS_PER_SECOND); // Avoids % operation.
77 
78     clockid_t clockId = CLOCK_MONOTONIC;
79     const int relativeFlag = 0; // flag of relative sleep.
80     ret = clock_nanosleep(clockId, relativeFlag, &time, nullptr);
81     if (ret != 0) {
82         AUDIO_WARNING_LOG("RelativeSleep may failed, ret is :%{public}d", ret);
83     }
84 
85     return ret;
86 }
87 
Count(const std::string & value,int64_t count,bool isEnable)88 void Trace::Count(const std::string &value, int64_t count, bool isEnable)
89 {
90 #ifdef FEATURE_HITRACE_METER
91     CountTraceDebug(isEnable, HITRACE_TAG_ZAUDIO, value, count);
92 #endif
93 }
94 
Trace(const std::string & value,bool isShowLog,bool isEnable)95 Trace::Trace(const std::string &value, bool isShowLog, bool isEnable)
96 {
97     value_ = value;
98     isShowLog_ = isShowLog;
99     isEnable_ = isEnable;
100     isFinished_ = false;
101 #ifdef FEATURE_HITRACE_METER
102     if (isShowLog) {
103         isShowLog_ = true;
104         AUDIO_INFO_LOG("%{public}s start.", value_.c_str());
105     }
106     StartTraceDebug(isEnable_, HITRACE_TAG_ZAUDIO, value);
107 #endif
108 }
109 
End()110 void Trace::End()
111 {
112 #ifdef FEATURE_HITRACE_METER
113     if (!isFinished_) {
114         FinishTraceDebug(isEnable_, HITRACE_TAG_ZAUDIO);
115         isFinished_ = true;
116         if (isShowLog_) {
117             AUDIO_INFO_LOG("%{public}s end.", value_.c_str());
118         }
119     }
120 #endif
121 }
122 
~Trace()123 Trace::~Trace()
124 {
125     End();
126 }
127 
AudioXCollie(const std::string & tag,uint32_t timeoutSeconds,std::function<void (void *)> func,void * arg,uint32_t flag)128 AudioXCollie::AudioXCollie(const std::string &tag, uint32_t timeoutSeconds,
129     std::function<void(void *)> func, void *arg, uint32_t flag)
130 {
131     AUDIO_DEBUG_LOG("Start AudioXCollie, tag: %{public}s, timeoutSeconds: %{public}u, flag: %{public}u",
132         tag.c_str(), timeoutSeconds, flag);
133     id_ = HiviewDFX::XCollie::GetInstance().SetTimer(tag, timeoutSeconds, func, arg, flag);
134     tag_ = tag;
135     isCanceled_ = false;
136 }
137 
~AudioXCollie()138 AudioXCollie::~AudioXCollie()
139 {
140     CancelXCollieTimer();
141 }
142 
CancelXCollieTimer()143 void AudioXCollie::CancelXCollieTimer()
144 {
145     if (!isCanceled_) {
146         HiviewDFX::XCollie::GetInstance().CancelTimer(id_);
147         isCanceled_ = true;
148         AUDIO_DEBUG_LOG("CancelXCollieTimer: cancel timer %{public}s", tag_.c_str());
149     }
150 }
151 
VerifyIsSystemApp()152 bool PermissionUtil::VerifyIsSystemApp()
153 {
154     uint64_t fullTokenId = IPCSkeleton::GetCallingFullTokenID();
155     bool tmp = Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(fullTokenId);
156     CHECK_AND_RETURN_RET(!tmp, true);
157 
158     AUDIO_ERR_LOG("Check system app permission reject");
159     return false;
160 }
161 
VerifySelfPermission()162 bool PermissionUtil::VerifySelfPermission()
163 {
164     Security::AccessToken::FullTokenID selfToken = IPCSkeleton::GetSelfTokenID();
165 
166     auto tokenTypeFlag = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(static_cast<uint32_t>(selfToken));
167 
168     CHECK_AND_RETURN_RET(tokenTypeFlag != Security::AccessToken::TOKEN_NATIVE, true);
169 
170     CHECK_AND_RETURN_RET(tokenTypeFlag != Security::AccessToken::TOKEN_SHELL, true);
171 
172     bool tmp = Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(selfToken);
173     CHECK_AND_RETURN_RET(!tmp, true);
174 
175     AUDIO_ERR_LOG("Check self app permission reject");
176     return false;
177 }
178 
VerifySystemPermission()179 bool PermissionUtil::VerifySystemPermission()
180 {
181     auto tokenId = IPCSkeleton::GetCallingTokenID();
182     auto tokenTypeFlag = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId);
183 
184     CHECK_AND_RETURN_RET(tokenTypeFlag != Security::AccessToken::TOKEN_NATIVE, true);
185 
186     CHECK_AND_RETURN_RET(tokenTypeFlag != Security::AccessToken::TOKEN_SHELL, true);
187 
188     bool tmp = VerifyIsSystemApp();
189     CHECK_AND_RETURN_RET(!tmp, true);
190 
191     AUDIO_ERR_LOG("Check system permission reject");
192     return false;
193 }
194 
AdjustStereoToMonoForPCM8Bit(int8_t * data,uint64_t len)195 void AdjustStereoToMonoForPCM8Bit(int8_t *data, uint64_t len)
196 {
197     // the number 2: stereo audio has 2 channels
198     uint64_t count = len / 2;
199 
200     while (count > 0) {
201         // the number 2 is the count of stereo audio channels
202         data[0] = data[0] / 2 + data[1] / 2;
203         data[1] = data[0];
204         data += 2;
205         count--;
206     }
207 }
208 
AdjustStereoToMonoForPCM16Bit(int16_t * data,uint64_t len)209 void AdjustStereoToMonoForPCM16Bit(int16_t *data, uint64_t len)
210 {
211     uint64_t count = len / 2 / 2;
212     // first number 2: stereo audio has 2 channels
213     // second number 2: the bit depth of PCM16Bit is 16 bits (2 bytes)
214 
215     while (count > 0) {
216         // the number 2 is the count of stereo audio channels
217         data[0] = data[0] / 2 + data[1] / 2;
218         data[1] = data[0];
219         data += 2;
220         count--;
221     }
222 }
223 
AdjustStereoToMonoForPCM24Bit(int8_t * data,uint64_t len)224 void AdjustStereoToMonoForPCM24Bit(int8_t *data, uint64_t len)
225 {
226     uint64_t count = len / 2 / 3;
227     // first number 2: stereo audio has 2 channels
228     // second number 3: the bit depth of PCM24Bit is 24 bits (3 bytes)
229 
230     // int8_t is used for reading data of PCM24BIT here
231     // 24 / 8 = 3, so we need repeat the calculation three times in each loop
232     while (count > 0) {
233         // the number 2 is the count of stereo audio channels, 2 * 3 = 6
234         data[0] = data[0] / 2 + data[3] / 2;
235         data[3] = data[0];
236         data[1] = data[1] / 2 + data[4] / 2;
237         data[4] = data[1];
238         data[2] = data[2] / 2 + data[5] / 2;
239         data[5] = data[2];
240         data += 6;
241         count--;
242     }
243 }
244 
AdjustStereoToMonoForPCM32Bit(int32_t * data,uint64_t len)245 void AdjustStereoToMonoForPCM32Bit(int32_t *data, uint64_t len)
246 {
247     uint64_t count = len / 2 / 4;
248     // first number 2: stereo audio has 2 channels
249     // second number 4: the bit depth of PCM32Bit is 32 bits (4 bytes)
250 
251     while (count > 0) {
252         // the number 2 is the count of stereo audio channels
253         data[0] = data[0] / 2 + data[1] / 2;
254         data[1] = data[0];
255         data += 2;
256         count--;
257     }
258 }
259 
AdjustAudioBalanceForPCM8Bit(int8_t * data,uint64_t len,float left,float right)260 void AdjustAudioBalanceForPCM8Bit(int8_t *data, uint64_t len, float left, float right)
261 {
262     uint64_t count = len / 2;
263     // the number 2: stereo audio has 2 channels
264 
265     while (count > 0) {
266         // the number 2 is the count of stereo audio channels
267         data[0] *= left;
268         data[1] *= right;
269         data += 2;
270         count--;
271     }
272 }
273 
AdjustAudioBalanceForPCM16Bit(int16_t * data,uint64_t len,float left,float right)274 void AdjustAudioBalanceForPCM16Bit(int16_t *data, uint64_t len, float left, float right)
275 {
276     uint64_t count = len / 2 / 2;
277     // first number 2: stereo audio has 2 channels
278     // second number 2: the bit depth of PCM16Bit is 16 bits (2 bytes)
279 
280     while (count > 0) {
281         // the number 2 is the count of stereo audio channels
282         data[0] *= left;
283         data[1] *= right;
284         data += 2;
285         count--;
286     }
287 }
288 
AdjustAudioBalanceForPCM24Bit(int8_t * data,uint64_t len,float left,float right)289 void AdjustAudioBalanceForPCM24Bit(int8_t *data, uint64_t len, float left, float right)
290 {
291     uint64_t count = len / 2 / 3;
292     // first number 2: stereo audio has 2 channels
293     // second number 3: the bit depth of PCM24Bit is 24 bits (3 bytes)
294 
295     // int8_t is used for reading data of PCM24BIT here
296     // 24 / 8 = 3, so we need repeat the calculation three times in each loop
297     while (count > 0) {
298         // the number 2 is the count of stereo audio channels, 2 * 3 = 6
299         data[0] *= left;
300         data[1] *= left;
301         data[2] *= left;
302         data[3] *= right;
303         data[4] *= right;
304         data[5] *= right;
305         data += 6;
306         count--;
307     }
308 }
309 
AdjustAudioBalanceForPCM32Bit(int32_t * data,uint64_t len,float left,float right)310 void AdjustAudioBalanceForPCM32Bit(int32_t *data, uint64_t len, float left, float right)
311 {
312     uint64_t count = len / 2 / 4;
313     // first number 2: stereo audio has 2 channels
314     // second number 4: the bit depth of PCM32Bit is 32 bits (4 bytes)
315 
316     while (count > 0) {
317         // the number 2 is the count of stereo audio channels
318         data[0] *= left;
319         data[1] *= right;
320         data += 2;
321         count--;
322     }
323 }
324 
Read24Bit(const uint8_t * p)325 uint32_t Read24Bit(const uint8_t *p)
326 {
327     return ((uint32_t) p[BIT_DEPTH_TWO] << BIT_16) | ((uint32_t) p[1] << BIT_8) | ((uint32_t) p[0]);
328 }
329 
Write24Bit(uint8_t * p,uint32_t u)330 void Write24Bit(uint8_t *p, uint32_t u)
331 {
332     p[BIT_DEPTH_TWO] = (uint8_t) (u >> BIT_16);
333     p[1] = static_cast<uint8_t>(u >> BIT_8);
334     p[0] = static_cast<uint8_t>(u);
335 }
336 
ConvertFrom24BitToFloat(unsigned n,const uint8_t * a,float * b)337 void ConvertFrom24BitToFloat(unsigned n, const uint8_t *a, float *b)
338 {
339     for (; n > 0; n--) {
340         int32_t s = Read24Bit(a) << BIT_8;
341         *b = s * (1.0f / (1U << (BIT_32 - 1)));
342         a += OFFSET_BIT_24;
343         b++;
344     }
345 }
346 
ConvertFrom32BitToFloat(unsigned n,const int32_t * a,float * b)347 void ConvertFrom32BitToFloat(unsigned n, const int32_t *a, float *b)
348 {
349     for (; n > 0; n--) {
350         *(b++) = *(a++) * (1.0f / (1U << (BIT_32 - 1)));
351     }
352 }
353 
CapMax(float v)354 float CapMax(float v)
355 {
356     float value = v;
357     if (v > 1.0f) {
358         value = 1.0f - FLOAT_EPS;
359     } else if (v < -1.0f) {
360         value = -1.0f + FLOAT_EPS;
361     }
362     return value;
363 }
364 
ConvertFromFloatTo24Bit(unsigned n,const float * a,uint8_t * b)365 void ConvertFromFloatTo24Bit(unsigned n, const float *a, uint8_t *b)
366 {
367     for (; n > 0; n--) {
368         float tmp = *a++;
369         float v = CapMax(tmp) * (1U << (BIT_32 - 1));
370         Write24Bit(b, (static_cast<int32_t>(v)) >> BIT_8);
371         b += OFFSET_BIT_24;
372     }
373 }
374 
ConvertFromFloatTo32Bit(unsigned n,const float * a,int32_t * b)375 void ConvertFromFloatTo32Bit(unsigned n, const float *a, int32_t *b)
376 {
377     for (; n > 0; n--) {
378         float tmp = *a++;
379         float v = CapMax(tmp) * (1U << (BIT_32 - 1));
380         *(b++) = static_cast<int32_t>(v);
381     }
382 }
383 
384 template <typename T>
GetSysPara(const char * key,T & value)385 bool GetSysPara(const char *key, T &value)
386 {
387     CHECK_AND_RETURN_RET_LOG(key != nullptr, false, "key is nullptr");
388     char paraValue[20] = {0}; // 20 for system parameter
389     auto res = GetParameter(key, "-1", paraValue, sizeof(paraValue));
390 
391     CHECK_AND_RETURN_RET_LOG(res > 0, false, "GetSysPara fail, key:%{public}s res:%{public}d", key, res);
392     AUDIO_DEBUG_LOG("key:%{public}s value:%{public}s", key, paraValue);
393     std::stringstream valueStr;
394     valueStr << paraValue;
395     valueStr >> value;
396     return true;
397 }
398 
399 template bool GetSysPara(const char *key, int32_t &value);
400 template bool GetSysPara(const char *key, uint32_t &value);
401 template bool GetSysPara(const char *key, int64_t &value);
402 template bool GetSysPara(const char *key, std::string &value);
403 
404 std::map<std::string, std::string> DumpFileUtil::g_lastPara = {};
405 
OpenDumpFileInner(std::string para,std::string fileName,AudioDumpFileType fileType)406 FILE *DumpFileUtil::OpenDumpFileInner(std::string para, std::string fileName, AudioDumpFileType fileType)
407 {
408     std::string filePath;
409     switch (fileType) {
410         case AUDIO_APP:
411             filePath = DUMP_APP_DIR + fileName;
412             break;
413         case AUDIO_SERVICE:
414             filePath = DUMP_SERVICE_DIR + fileName;
415             break;
416         case AUDIO_PULSE:
417             filePath = DUMP_PULSE_DIR + fileName;
418             break;
419         default:
420             AUDIO_ERR_LOG("Invalid AudioDumpFileType");
421             break;
422     }
423     std::string dumpPara;
424     FILE *dumpFile = nullptr;
425     bool res = GetSysPara(para.c_str(), dumpPara);
426     if (!res || dumpPara.empty()) {
427         AUDIO_INFO_LOG("%{public}s is not set, dump audio is not required", para.c_str());
428         g_lastPara[para] = dumpPara;
429         return dumpFile;
430     }
431     AUDIO_DEBUG_LOG("%{public}s = %{public}s", para.c_str(), dumpPara.c_str());
432     if (dumpPara == "w") {
433         dumpFile = fopen(filePath.c_str(), "wb+");
434         CHECK_AND_RETURN_RET_LOG(dumpFile != nullptr, dumpFile,
435             "Error opening pcm test file!");
436     } else if (dumpPara == "a") {
437         dumpFile = fopen(filePath.c_str(), "ab+");
438         CHECK_AND_RETURN_RET_LOG(dumpFile != nullptr, dumpFile,
439             "Error opening pcm test file!");
440     }
441     g_lastPara[para] = dumpPara;
442     return dumpFile;
443 }
444 
WriteDumpFile(FILE * dumpFile,void * buffer,size_t bufferSize)445 void DumpFileUtil::WriteDumpFile(FILE *dumpFile, void *buffer, size_t bufferSize)
446 {
447     if (dumpFile == nullptr) {
448         return;
449     }
450     CHECK_AND_RETURN_LOG(buffer != nullptr, "Invalid write param");
451     size_t writeResult = fwrite(buffer, 1, bufferSize, dumpFile);
452     CHECK_AND_RETURN_LOG(writeResult == bufferSize, "Failed to write the file.");
453 }
454 
CloseDumpFile(FILE ** dumpFile)455 void DumpFileUtil::CloseDumpFile(FILE **dumpFile)
456 {
457     if (*dumpFile) {
458         fclose(*dumpFile);
459         *dumpFile = nullptr;
460     }
461 }
462 
ChangeDumpFileState(std::string para,FILE ** dumpFile,std::string filePath)463 void DumpFileUtil::ChangeDumpFileState(std::string para, FILE **dumpFile, std::string filePath)
464 {
465     CHECK_AND_RETURN_LOG(*dumpFile != nullptr, "Invalid file para");
466     CHECK_AND_RETURN_LOG(g_lastPara[para] == "w" || g_lastPara[para] == "a", "Invalid input para");
467     std::string dumpPara;
468     bool res = GetSysPara(para.c_str(), dumpPara);
469     if (!res || dumpPara.empty()) {
470         AUDIO_WARNING_LOG("get %{public}s fail", para.c_str());
471     }
472     if (g_lastPara[para] == "w" && dumpPara == "w") {
473         return;
474     }
475     CloseDumpFile(dumpFile);
476     OpenDumpFile(para, filePath, dumpFile);
477 }
478 
OpenDumpFile(std::string para,std::string fileName,FILE ** file)479 void DumpFileUtil::OpenDumpFile(std::string para, std::string fileName, FILE **file)
480 {
481     if (*file != nullptr) {
482         DumpFileUtil::ChangeDumpFileState(para, file, fileName);
483         return;
484     }
485     if (para == DUMP_SERVER_PARA) {
486         if (fileName == DUMP_BLUETOOTH_RENDER_SINK_FILENAME || fileName == DUMP_RENDER_SINK_FILENAME ||
487             fileName == DUMP_CAPTURER_SOURCE_FILENAME || fileName == DUMP_OFFLOAD_RENDER_SINK_FILENAME) {
488             *file = DumpFileUtil::OpenDumpFileInner(para, fileName, AUDIO_PULSE);
489             return;
490         }
491         *file = DumpFileUtil::OpenDumpFileInner(para, fileName, AUDIO_SERVICE);
492     } else {
493         *file = DumpFileUtil::OpenDumpFileInner(para, fileName, AUDIO_APP);
494         if (*file == nullptr) {
495             *file = DumpFileUtil::OpenDumpFileInner(para, fileName, AUDIO_SERVICE);
496         }
497     }
498 }
499 
500 } // namespace AudioStandard
501 } // namespace OHOS
502 
503 #ifdef __cplusplus
504 extern "C" {
505 #endif
506 
507 struct CTrace {
CTraceCTrace508     explicit CTrace(const char *traceName) : trace(OHOS::AudioStandard::Trace(traceName)) {};
509     OHOS::AudioStandard::Trace trace;
510 };
511 
GetAndStart(const char * traceName)512 CTrace *GetAndStart(const char *traceName)
513 {
514     std::unique_ptr<CTrace> cTrace = std::make_unique<CTrace>(traceName);
515 
516     return cTrace.release();
517 }
518 
EndCTrace(CTrace * cTrace)519 void EndCTrace(CTrace *cTrace)
520 {
521     if (cTrace != nullptr) {
522         cTrace->trace.End();
523     }
524 }
525 
CTraceCount(const char * traceName,int64_t count)526 void CTraceCount(const char *traceName, int64_t count)
527 {
528     OHOS::AudioStandard::Trace::Count(traceName, count);
529 }
530 
CallEndAndClear(CTrace ** cTrace)531 void CallEndAndClear(CTrace **cTrace)
532 {
533     if (cTrace != nullptr && *cTrace != nullptr) {
534         EndCTrace(*cTrace);
535         delete *cTrace;
536         *cTrace = nullptr;
537     }
538 }
539 
540 #ifdef __cplusplus
541 }
542 #endif
543