• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-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 #ifndef AUDIO_UTILS_H
16 #define AUDIO_UTILS_H
17 
18 #include <cstdint>
19 #include <string>
20 #include <list>
21 #include <map>
22 #include <unordered_map>
23 #include <mutex>
24 #include <ctime>
25 #include <sys/time.h>
26 #include <atomic>
27 #include <cstdio>
28 #include <queue>
29 #include <climits>
30 #include <condition_variable>
31 #include <charconv>
32 #include <unistd.h>
33 #include "securec.h"
34 
35 #include "audio_info.h"
36 #include "audio_common_utils.h"
37 
38 #define AUDIO_MS_PER_SECOND 1000
39 #define AUDIO_US_PER_SECOND 1000000
40 #define AUDIO_NS_PER_MILLISECOND 1000000
41 #define AUDIO_NS_PER_SECOND ((uint64_t)1000000000)
42 
43 #define FLOAT_EPS 1e-9f
44 #define OFFSET_BIT_24 3
45 #define BIT_DEPTH_TWO 2
46 #define BIT_8 8
47 #define BIT_16 16
48 #define BIT_24 24
49 #define BIT_32 32
50 namespace OHOS {
51 namespace AudioStandard {
52 const uint32_t STRING_BUFFER_SIZE = 4096;
53 const size_t MILLISECOND_PER_SECOND = 1000;
54 const int32_t GET_EXTRA_PARAM_LEN = 200;
55 const uint32_t AUDIO_ID = 1041;
56 
57 // Ringer or alarmer dual tone
58 const size_t AUDIO_CONCURRENT_ACTIVE_DEVICES_LIMIT = 2;
59 
60 constexpr int32_t AUDIO_EXTRA_PARAMETERS_COUNT_UPPER_LIMIT = 40;
61 constexpr int32_t AUDIO_EFFECT_CHAIN_COUNT_UPPER_LIMIT = 32;
62 
63 /* Define AudioXcollie timeout flag, consistent with xcollie_define.h in hiviewdfx  */
64 static constexpr unsigned int AUDIO_XCOLLIE_FLAG_DEFAULT = (~0); // do all callback function
65 static constexpr unsigned int AUDIO_XCOLLIE_FLAG_NOOP = (0); // do nothing but the caller defined function
66 static constexpr unsigned int AUDIO_XCOLLIE_FLAG_LOG = (1 << 0); // generate log file
67 static constexpr unsigned int AUDIO_XCOLLIE_FLAG_RECOVERY = (1 << 1); // die when timeout
68 
69 class Util {
70 public:
71     static bool IsScoSupportSource(const SourceType sourceType);
72 
73     static bool IsDualToneStreamType(const AudioStreamType streamType);
74 
75     static bool IsRingerOrAlarmerStreamUsage(const StreamUsage &usage);
76 
77     static bool IsRingerAudioScene(const AudioScene &audioScene);
78 
79     static uint32_t GetSamplePerFrame(const AudioSampleFormat &format);
80 };
81 
82 class Trace {
83 public:
84     static void Count(const std::string &value, int64_t count);
85     // Show if data is silent.
86     static void CountVolume(const std::string &value, uint8_t data);
87     Trace(const std::string &value);
88     void End();
89     ~Trace();
90 private:
91     bool isFinished_;
92 };
93 
94 class AudioXCollie {
95 public:
96     AudioXCollie(const std::string &tag, uint32_t timeoutSeconds,
97         std::function<void(void *)> func = nullptr, void *arg = nullptr, uint32_t flag = 0);
98     ~AudioXCollie();
99     void CancelXCollieTimer();
100 private:
101     int32_t id_;
102     std::string tag_;
103     bool isCanceled_;
104 };
105 
106 class CheckoutSystemAppUtil {
107 public:
108     static bool CheckoutSystemApp(int32_t uid);
109 };
110 
111 class ClockTime {
112 public:
113     static int64_t GetCurNano();
114     static int64_t GetRealNano();
115     static int64_t GetBootNano();
116     static int32_t AbsoluteSleep(int64_t nanoTime);
117     static int32_t RelativeSleep(int64_t nanoTime);
118     static std::string NanoTimeToString(int64_t nanoTime);
119 
120     static void GetAllTimeStamp(std::vector<uint64_t> &timestamps);
121 };
122 
123 /**
124  * Example 1: Use specific timeout call Check().
125  *     WatchTimeout guard("DoSomeWorkFunction", 50 * AUDIO_US_PER_SECOND); // if func cost more than 50 ms, print log
126  *     DoSomeWorkFunction();
127  *     guard.CheckCurrTimeout();
128  * Example 2: Use default timeout(40ms) and auto-check in release.
129  *     WatchTimeout guard("DoSomeWorkFunction")
130  *     DoSomeWorkFunction();
131  */
132 class WatchTimeout {
133 public:
134     static constexpr int64_t DEFAULT_TIMEOUT_NS = 40 * 1000 * 1000;
135     WatchTimeout(const std::string &funcName, int64_t timeoutNs = DEFAULT_TIMEOUT_NS);
136     ~WatchTimeout();
137     void CheckCurrTimeout();
138 private:
139     const std::string funcName_;
140     int64_t timeoutNs_ = 0;
141     int64_t startTimeNs_ = 0;
142     bool isChecked_ = false;
143 };
144 
145 class PermissionUtil {
146 public:
147     static bool IsFoldAble(const char ch);
148     static void UpdateBGSet();
149     static bool VerifyIsAudio();
150     static bool VerifyIsShell();
151     static bool VerifyIsSystemApp();
152     static bool VerifySelfPermission();
153     static bool VerifySystemPermission();
154     static bool VerifyPermission(const std::string &permissionName, uint32_t tokenId);
155     static bool NeedVerifyBackgroundCapture(int32_t callingUid, SourceType sourceType);
156     static bool VerifyBackgroundCapture(uint32_t tokenId, uint64_t fullTokenId);
157     static bool NotifyPrivacyStart(uint32_t targetTokenId, uint32_t sessionId);
158     static bool NotifyPrivacyStop(uint32_t targetTokenId, uint32_t sessionId);
159     static int32_t StartUsingPermission(uint32_t targetTokenId, const char* permission);
160     static int32_t StopUsingPermission(uint32_t targetTokenId, const char* permission);
161     static bool CheckCallingUidPermission(const std::vector<uid_t> &allowedUids);
162 };
163 
164 class SwitchStreamUtil {
165 public:
166     static bool UpdateSwitchStreamRecord(SwitchStreamInfo &info, SwitchState targetState);
167     static bool IsSwitchStreamSwitching(SwitchStreamInfo &info, SwitchState targetState);
168 private:
169     static bool InsertSwitchStreamRecord(SwitchStreamInfo &info, SwitchState targetState);
170     static bool RemoveSwitchStreamRecord(SwitchStreamInfo &info, SwitchState targetState);
171     static bool HandleCreatedSwitchInfoInRecord(SwitchStreamInfo &info, SwitchState targetState);
172     static bool HandleStartedSwitchInfoInRecord(SwitchStreamInfo &info, SwitchState targetState);
173     static bool HandleSwitchInfoInRecord(SwitchStreamInfo &info, SwitchState targetState);
174     static void TimeoutThreadHandleTimeoutRecord(SwitchStreamInfo info, SwitchState targetState);
175     static bool RemoveAllRecordBySessionId(uint32_t sessionId);
176 };
177 
178 void AdjustStereoToMonoForPCM8Bit(int8_t *data, uint64_t len);
179 void AdjustStereoToMonoForPCM16Bit(int16_t *data, uint64_t len);
180 void AdjustStereoToMonoForPCM24Bit(uint8_t *data, uint64_t len);
181 void AdjustStereoToMonoForPCM32Bit(int32_t *data, uint64_t len);
182 void AdjustAudioBalanceForPCM8Bit(int8_t *data, uint64_t len, float left, float right);
183 void AdjustAudioBalanceForPCM16Bit(int16_t *data, uint64_t len, float left, float right);
184 void AdjustAudioBalanceForPCM24Bit(uint8_t *data, uint64_t len, float left, float right);
185 void AdjustAudioBalanceForPCM32Bit(int32_t *data, uint64_t len, float left, float right);
186 
187 void ConvertFrom24BitToFloat(unsigned n, const uint8_t *a, float *b);
188 void ConvertFrom32BitToFloat(unsigned n, const int32_t *a, float *b);
189 void ConvertFromFloatTo24Bit(unsigned n, const float *a, uint8_t *b);
190 void ConvertFromFloatTo32Bit(unsigned n, const float *a, int32_t *b);
191 
192 std::string GetEncryptStr(const std::string &str);
193 std::string ConvertNetworkId(const std::string &networkId);
194 std::string Hide(const std::string &str);
195 
196 enum ConvertHdiFormat {
197     SAMPLE_U8_C = 0,
198     SAMPLE_S16_C = 1,
199     SAMPLE_S24_C = 2,
200     SAMPLE_S32_C = 3,
201     SAMPLE_F32_C = 4,
202     INVALID_WIDTH_C = -1
203 }; // same with HdiAdapterFormat
204 
205 float UpdateMaxAmplitude(ConvertHdiFormat adapterFormat, char *frame, uint64_t replyBytes);
206 float CalculateMaxAmplitudeForPCM8Bit(int8_t *frame, uint64_t nSamples);
207 float CalculateMaxAmplitudeForPCM16Bit(int16_t *frame, uint64_t nSamples);
208 float CalculateMaxAmplitudeForPCM24Bit(char *frame, uint64_t nSamples);
209 float CalculateMaxAmplitudeForPCM32Bit(int32_t *frame, uint64_t nSamples);
210 
211 template <typename T>
212 bool isEqual(T a, T b, double precision = 0.01)
213 {
214     return std::abs(a - b) < precision;
215 }
216 
217 // return true if value is not in the array.
218 template <typename V>
NotContain(const std::vector<V> & array,const V & value)219 inline bool NotContain(const std::vector<V> &array, const V &value)
220 {
221     return std::find(array.begin(), array.end(), value) == array.end();
222 }
223 
224 template <typename T>
225 bool StringConverter(const std::string &str, T &result);
226 bool StringConverterFloat(const std::string &str, float &result);
227 
228 bool SetSysPara(const std::string& key, int32_t value);
229 template <typename T>
230 bool GetSysPara(const char *key, T &value);
231 
232 int32_t GetEngineFlag();
233 
234 enum AudioDumpFileType {
235     AUDIO_APP = 0,
236     OTHER_NATIVE_SERVICE = 1,
237     AUDIO_PULSE = 2,
238 };
239 
240 class DumpFileUtil {
241 public:
242     static constexpr char DUMP_SERVER_PARA[] = "sys.audio.dump.writeserver.enable";
243     static constexpr char DUMP_CLIENT_PARA[] = "sys.audio.dump.writeclient.enable";
244     static constexpr uint32_t PARAM_VALUE_LENTH = 150;
245     static constexpr char BETA_VERSION[] = "beta";
246     static void WriteDumpFile(FILE *dumpFile, void *buffer, size_t bufferSize);
247     static void CloseDumpFile(FILE **dumpFile);
248     static std::map<std::string, std::string> g_lastPara;
249     static void OpenDumpFile(std::string para, std::string fileName, FILE **file);
250 private:
251     static FILE *OpenDumpFileInner(std::string para, std::string fileName, AudioDumpFileType fileType);
252     static void ChangeDumpFileState(std::string para, FILE **dumpFile, std::string fileName);
253 };
254 
255 template <typename...Args>
AppendFormat(std::string & out,const char * fmt,Args &&...args)256 void AppendFormat(std::string& out, const char* fmt, Args&& ... args)
257 {
258     char buf[STRING_BUFFER_SIZE] = {0};
259     int len = ::sprintf_s(buf, sizeof(buf), fmt, std::forward<Args>(args)...);
260     if (len <= 0) {
261         return;
262     }
263     out += buf;
264 }
265 
266 class AudioInfoDumpUtils {
267 public:
268     static const std::string GetStreamName(AudioStreamType streamType);
269     static const std::string GetDeviceTypeName(DeviceType deviceType);
270     static const std::string GetConnectTypeName(ConnectType connectType);
271     static const std::string GetSourceName(SourceType sourceType);
272     static const std::string GetDeviceVolumeTypeName(DeviceVolumeType deviceType);
273 };
274 
275 template<typename T>
276 class ObjectRefMap {
277 public:
278     static std::mutex allObjLock;
279     static std::map<T*, uint32_t> refMap;
280     static void Insert(T *obj);
281     static void Erase(T *obj);
282     static T *IncreaseRef(T *obj);
283     static void DecreaseRef(T *obj);
284 
285     ObjectRefMap(T *obj);
286     ~ObjectRefMap();
287     T *GetPtr();
288 
289 private:
290     T *obj_ = nullptr;
291 };
292 
293 template <typename T>
294 std::mutex ObjectRefMap<T>::allObjLock;
295 
296 template <typename T>
297 std::map<T *, uint32_t> ObjectRefMap<T>::refMap;
298 
299 template <typename T>
Insert(T * obj)300 void ObjectRefMap<T>::Insert(T *obj)
301 {
302     std::lock_guard<std::mutex> lock(allObjLock);
303     refMap[obj] = 1;
304 }
305 
306 template <typename T>
Erase(T * obj)307 void ObjectRefMap<T>::Erase(T *obj)
308 {
309     std::lock_guard<std::mutex> lock(allObjLock);
310     auto it = refMap.find(obj);
311     if (it != refMap.end()) {
312         refMap.erase(it);
313     }
314 }
315 
316 template <typename T>
IncreaseRef(T * obj)317 T *ObjectRefMap<T>::IncreaseRef(T *obj)
318 {
319     std::lock_guard<std::mutex> lock(allObjLock);
320     if (refMap.count(obj)) {
321         refMap[obj]++;
322         return obj;
323     } else {
324         return nullptr;
325     }
326 }
327 
328 template <typename T>
DecreaseRef(T * obj)329 void ObjectRefMap<T>::DecreaseRef(T *obj)
330 {
331     std::unique_lock<std::mutex> lock(allObjLock);
332     if (refMap.count(obj) && --refMap[obj] == 0) {
333         refMap.erase(obj);
334         lock.unlock();
335         delete obj;
336         obj = nullptr;
337     }
338 }
339 
340 template <typename T>
ObjectRefMap(T * obj)341 ObjectRefMap<T>::ObjectRefMap(T *obj)
342 {
343     if (obj != nullptr) {
344         obj_ = ObjectRefMap::IncreaseRef(obj);
345     }
346 }
347 
348 template <typename T>
~ObjectRefMap()349 ObjectRefMap<T>::~ObjectRefMap()
350 {
351     if (obj_ != nullptr) {
352         ObjectRefMap::DecreaseRef(obj_);
353     }
354 }
355 
356 template <typename T>
GetPtr()357 T *ObjectRefMap<T>::GetPtr()
358 {
359     return obj_;
360 }
361 
362 template <typename Key, typename T>
363 auto SafeGetMap(const std::unordered_map<Key, std::shared_ptr<T>>& map, Key key)
364     -> std::shared_ptr<T>
365 {
366     auto it = map.find(key);
367     return (it != map.end() && it->second) ? it->second : nullptr;
368 }
369 
370 std::string GetTime();
371 
372 int32_t GetFormatByteSize(int32_t format);
373 
374 struct SignalDetectAgent {
375     bool CheckAudioData(uint8_t *buffer, size_t bufferLen);
376     bool DetectSignalData(int32_t *buffer, size_t bufferLen);
377     void ResetDetectResult();
378     int32_t channels_ = STEREO;
379     int32_t sampleRate_ = SAMPLE_RATE_48000;
380     int32_t sampleFormat_ = SAMPLE_S16LE;
381     int32_t formatByteSize_;
382     int32_t lastPeakSignal_ = SHRT_MIN;
383     int32_t lastPeakSignalPos_ = 0;
384     int32_t blankPeriod_ = 0;
385     size_t frameCountIgnoreChannel_;
386     bool hasFirstNoneZero_ = false;
387     bool blankHaveOutput_ = true;
388     bool dspTimestampGot_ = false;
389     bool signalDetected_ = false;
390     std::string lastPeakBufferTime_ = "";
391     std::vector<int32_t> cacheAudioData_;
392 };
393 
394 class AudioLatencyMeasurement {
395 public:
396     // static methods, invoked without instantiation in sinks and sources
397     static bool CheckIfEnabled();
398     AudioLatencyMeasurement(const int32_t &sampleRate, const int32_t &channelCount,
399         const int32_t &sampleFormat, const std::string &appName, const uint32_t &sessionId);
400     ~AudioLatencyMeasurement();
401 
402     // non-static methods, invoked after instantiation in AudioRenderer and AudioCapturer
403     void InitSignalData();
404     bool MockPcmData(uint8_t *buffer, size_t bufferLen); // mute data and insert signal data
405 private:
406     int32_t format_ = SAMPLE_S16LE;
407     int32_t formatByteSize_;
408     int32_t sampleRate_;
409     int32_t channelCount_;
410     uint32_t sessionId_;
411     size_t mockedTime_ = 0;
412     bool mockThisStream_ = false;
413     std::string appName_;
414     std::unique_ptr<int16_t[]> signalData_ = nullptr;
415 };
416 
417 class LatencyMonitor {
418 public:
419     static LatencyMonitor& GetInstance();
420     void ShowTimestamp(bool isRenderer);
421     void ShowBluetoothTimestamp();
422     void UpdateClientTime(bool isRenderer, std::string &timestamp);
423     void UpdateSinkOrSourceTime(bool isRenderer, std::string &timestamp);
424     void UpdateDspTime(std::string dspTime);
425 private:
426     std::string rendererMockTime_ = "";
427     std::string sinkDetectedTime_ = "";
428     std::string dspDetectedTime_ = "";
429     std::string capturerDetectedTime_ = "";
430     std::string sourceDetectedTime_ = "";
431     std::string dspBeforeSmartPa_ = "";
432     std::string dspAfterSmartPa_ = "";
433     std::string dspMockTime_ = "";
434     size_t extraStrLen_ = 0;
435 };
436 
437 class AudioDump {
438 public:
439     static AudioDump& GetInstance();
440     void SetVersionType(const std::string& versionType);
441     std::string GetVersionType();
442 private:
AudioDump()443     AudioDump() {}
~AudioDump()444     ~AudioDump() {}
445     std::string versionType_ = "commercial";
446 };
447 
448 template <typename EnumType, typename V>
GetKeyFromValue(const std::unordered_map<EnumType,V> & map,const V & value)449 int32_t GetKeyFromValue(const std::unordered_map<EnumType, V> &map, const V &value)
450 {
451     for (auto it : map) {
452         if (it.second == value) {
453             return it.first;
454         }
455     }
456     return -1;
457 }
458 
459 template <typename T, typename Compare>
CasWithCompare(std::atomic<T> & atomicVar,T newValue,Compare compare)460 bool CasWithCompare(std::atomic<T> &atomicVar, T newValue, Compare compare)
461 {
462     T old = atomicVar;
463     do {
464         if (!compare(old, newValue)) {
465             return false;
466         }
467     } while (!atomicVar.compare_exchange_weak(old, newValue));
468 
469     return true;
470 }
471 
472 template <typename T>
473 class FixedSizeList {
474 public:
FixedSizeList(size_t size)475     FixedSizeList(size_t size) : maxSize_(size), currentSize_(0), index_(0)
476     {
477         data_.resize(size);
478     }
479 
Add(T value)480     void Add(T value)
481     {
482         std::lock_guard<std::mutex> lock(mtx_);
483         data_[index_] = value;
484         index_ = (index_ + 1) % maxSize_;
485         if (currentSize_ < maxSize_) {
486             ++currentSize_;
487         }
488     }
489 
FindIf(const std::function<bool (const T &)> & predicate)490     std::optional<T> FindIf(const std::function<bool(const T&)>& predicate)
491     {
492         std::lock_guard<std::mutex> lock(mtx_);
493         for (size_t i = 0; i < currentSize_; ++i) {
494             if (predicate(data_[i])) {
495                 T result = data_[i];
496                 RemoveAt(i);
497                 return result;
498             }
499         }
500         return std::nullopt;
501     }
502 
Clear()503     void Clear()
504     {
505         std::lock_guard<std::mutex> lock(mtx_);
506         data_.clear();
507         data_.resize(maxSize_);
508         currentSize_ = 0;
509         index_ = 0;
510     }
511 
GetData()512     std::vector<T> GetData()
513     {
514         std::vector<T> dataInfo;
515         for (size_t i = 0; i < currentSize_; ++i) {
516             dataInfo.push_back(data_[i]);
517         }
518         return dataInfo;
519     }
520 
521 private:
RemoveAt(size_t position)522     void RemoveAt(size_t position)
523     {
524         if (position < currentSize_) {
525             for (size_t i = position; i < currentSize_ - 1; ++i) {
526                 data_[i] = data_[i + 1];
527             }
528             --currentSize_;
529             index_ = (index_ - 1 + maxSize_) % maxSize_;
530         }
531     }
532 
533     std::vector<T> data_;
534     size_t maxSize_;
535     size_t currentSize_;
536     size_t index_;
537     mutable std::mutex mtx_;  // mutable to allow const methods to lock the mutex
538 };
539 
540 enum AudioHdiUniqueIDBase : uint32_t {
541     // 0-4 is reserved for other modules
542     AUDIO_HDI_RENDER_ID_BASE = 5,
543     AUDIO_HDI_CAPTURE_ID_BASE = 6,
544 };
545 
546 enum HdiCaptureOffset : uint32_t {
547     HDI_CAPTURE_OFFSET_PRIMARY = 1,
548     HDI_CAPTURE_OFFSET_FAST = 2,
549     HDI_CAPTURE_OFFSET_REMOTE = 3,
550     HDI_CAPTURE_OFFSET_REMOTE_FAST = 4,
551     HDI_CAPTURE_OFFSET_USB = 5,
552     HDI_CAPTURE_OFFSET_EC = 6,
553     HDI_CAPTURE_OFFSET_MIC_REF = 7,
554     HDI_CAPTURE_OFFSET_WAKEUP = 8,
555     HDI_CAPTURE_OFFSET_BLUETOOTH = 9,
556     HDI_CAPTURE_OFFSET_ACCESSORY = 10,
557 };
558 
559 enum HdiRenderOffset : uint32_t {
560     HDI_RENDER_OFFSET_PRIMARY = 1,
561     HDI_RENDER_OFFSET_FAST = 2,
562     HDI_RENDER_OFFSET_REMOTE = 3,
563     HDI_RENDER_OFFSET_REMOTE_FAST = 4,
564     HDI_RENDER_OFFSET_BLUETOOTH = 5,
565     HDI_RENDER_OFFSET_OFFLOAD = 6,
566     HDI_RENDER_OFFSET_MULTICHANNEL = 7,
567     HDI_RENDER_OFFSET_DIRECT = 8,
568     HDI_RENDER_OFFSET_VOIP = 9,
569     HDI_RENDER_OFFSET_DP = 10,
570     HDI_RENDER_OFFSET_USB = 11,
571     HDI_RENDER_OFFSET_VOIP_FAST = 12,
572     HDI_RENDER_OFFSET_EAC3 = 13,
573     HDI_RENDER_OFFSET_REMOTE_OFFLOAD = 14,
574     HDI_RENDER_OFFSET_HEARING_AID = 15,
575 };
576 
577 uint32_t GenerateUniqueID(AudioHdiUniqueIDBase base, uint32_t offset);
578 
579 void CloseFd(int fd);
580 
581 int32_t CheckSupportedParams(const AudioStreamInfo &info);
582 
583 std::vector<std::map<AudioInterrupt, int32_t>> ToIpcInterrupts(
584     const std::list<std::pair<AudioInterrupt, AudioFocuState>> &from);
585 
586 std::list<std::pair<AudioInterrupt, AudioFocuState>> FromIpcInterrupts(
587     const std::vector<std::map<AudioInterrupt, int32_t>> &from);
588 
589 std::string GetBundleNameByToken(const uint32_t &tokenIdNum);
590 } // namespace AudioStandard
591 } // namespace OHOS
592 #endif // AUDIO_UTILS_H
593