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