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