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 /**
455  * @brief Provides interfaces for thread-safe blocking queues.
456  *
457  * The interfaces can be used to perform blocking and non-blocking push and
458  * pop operations on queues.
459  */
460 template <typename T>
461 class AudioSafeBlockQueue {
462 public:
AudioSafeBlockQueue(int capacity)463     explicit AudioSafeBlockQueue(int capacity) : maxSize_(capacity)
464     {
465     }
466 
467     /**
468      * @brief Inserts an element at the end of this queue in blocking mode.
469      *
470      * If the queue is full, the thread of the push operation will be blocked
471      * until the queue has space.
472      * If the queue is not full, the push operation can be performed and one of the
473      * pop threads (blocked when the queue is empty) is woken up.
474      *
475      * @param elem Indicates the element to insert.
476      */
Push(T const & elem)477     virtual void Push(T const& elem)
478     {
479         std::unique_lock<std::mutex> lock(mutexLock_);
480         while (queueT_.size() >= maxSize_) {
481             // If the queue is full, wait for jobs to be taken.
482             cvNotFull_.wait(lock, [&]() { return (queueT_.size() < maxSize_); });
483         }
484 
485         // Insert the element into the queue if the queue is not full.
486         queueT_.push(elem);
487         cvNotEmpty_.notify_all();
488     }
489 
490     /**
491      * @brief Removes the first element from this queue in blocking mode.
492      *
493      * If the queue is empty, the thread of the pop operation will be blocked
494      * until the queue has elements.
495      * If the queue is not empty, the pop operation can be performed, the first
496      * element of the queue is returned, and one of the push threads (blocked
497      * when the queue is full) is woken up.
498      */
Pop()499     T Pop()
500     {
501         std::unique_lock<std::mutex> lock(mutexLock_);
502 
503         while (queueT_.empty()) {
504             // If the queue is empty, wait for elements to be pushed in.
505             cvNotEmpty_.wait(lock, [&] { return !queueT_.empty(); });
506         }
507 
508         T elem = queueT_.front();
509         queueT_.pop();
510         cvNotFull_.notify_all();
511         return elem;
512     }
513 
514     /**
515      * @brief Inserts an element at the end of this queue in non-blocking mode.
516      *
517      * If the queue is full, <b>false</b> is returned directly.
518      * If the queue is not full, the push operation can be performed, one of the
519      * pop threads (blocked when the queue is empty) is woken up, and <b>true</b>
520      * is returned.
521      *
522      * @param elem Indicates the element to insert.
523      */
PushNoWait(T const & elem)524     virtual bool PushNoWait(T const& elem)
525     {
526         std::unique_lock<std::mutex> lock(mutexLock_);
527         if (queueT_.size() >= maxSize_) {
528             return false;
529         }
530         // Insert the element if the queue is not full.
531         queueT_.push(elem);
532         cvNotEmpty_.notify_all();
533         return true;
534     }
535 
536     /**
537      * @brief Removes the first element from this queue in non-blocking mode.
538      *
539      * If the queue is empty, <b>false</b> is returned directly.
540      * If the queue is not empty, the pop operation can be performed, one of the
541      * push threads (blocked when the queue is full) is woken up, and <b>true</b>
542      * is returned.
543      *
544      * @param outtask Indicates the data of the pop operation.
545      */
PopNotWait(T & outtask)546     bool PopNotWait(T& outtask)
547     {
548         std::unique_lock<std::mutex> lock(mutexLock_);
549         if (queueT_.empty()) {
550             return false;
551         }
552         outtask = queueT_.front();
553         queueT_.pop();
554 
555         cvNotFull_.notify_all();
556 
557         return true;
558     }
559 
PopAllNotWait()560     std::queue<T> PopAllNotWait()
561     {
562         std::queue<T> retQueue = {};
563         std::unique_lock<std::mutex> lock(mutexLock_);
564         retQueue.swap(queueT_);
565 
566         cvNotFull_.notify_all();
567 
568         return retQueue;
569     }
570 
Size()571     unsigned int Size()
572     {
573         std::unique_lock<std::mutex> lock(mutexLock_);
574         return queueT_.size();
575     }
576 
577     template< class Rep, class Period >
WaitNotEmptyFor(const std::chrono::duration<Rep,Period> & rel_time)578     void WaitNotEmptyFor(const std::chrono::duration<Rep, Period>& rel_time)
579     {
580         std::unique_lock<std::mutex> lock(mutexLock_);
581         cvNotEmpty_.wait_for(lock, rel_time, [this] {
582             return !queueT_.empty();
583         });
584     }
585 
IsEmpty()586     bool IsEmpty()
587     {
588         std::unique_lock<std::mutex> lock(mutexLock_);
589         return queueT_.empty();
590     }
591 
IsFull()592     bool IsFull()
593     {
594         std::unique_lock<std::mutex> lock(mutexLock_);
595         return queueT_.size() == maxSize_;
596     }
597 
Clear()598     void Clear()
599     {
600         std::unique_lock<std::mutex> lock(mutexLock_);
601         queueT_ = {};
602         cvNotFull_.notify_all();
603     }
604 
~AudioSafeBlockQueue()605     virtual ~AudioSafeBlockQueue() {}
606 
607 protected:
608     unsigned long maxSize_;  // Capacity of the queue
609     std::mutex mutexLock_;
610     std::condition_variable cvNotEmpty_;
611     std::condition_variable cvNotFull_;
612     std::queue<T> queueT_;
613 };
614 
615 enum AudioHdiUniqueIDBase : uint32_t {
616     // 0-4 is reserved for other modules
617     AUDIO_HDI_RENDER_ID_BASE = 5,
618     AUDIO_HDI_CAPTURE_ID_BASE = 6,
619 };
620 
621 enum HdiCaptureOffset : uint32_t {
622     HDI_CAPTURE_OFFSET_PRIMARY = 1,
623     HDI_CAPTURE_OFFSET_FAST = 2,
624     HDI_CAPTURE_OFFSET_REMOTE = 3,
625     HDI_CAPTURE_OFFSET_REMOTE_FAST = 4,
626     HDI_CAPTURE_OFFSET_USB = 5,
627     HDI_CAPTURE_OFFSET_EC = 6,
628     HDI_CAPTURE_OFFSET_MIC_REF = 7,
629     HDI_CAPTURE_OFFSET_WAKEUP = 8,
630 };
631 
632 enum HdiRenderOffset : uint32_t {
633     HDI_RENDER_OFFSET_PRIMARY = 1,
634     HDI_RENDER_OFFSET_FAST = 2,
635     HDI_RENDER_OFFSET_REMOTE = 3,
636     HDI_RENDER_OFFSET_REMOTE_FAST = 4,
637     HDI_RENDER_OFFSET_BLUETOOTH = 5,
638     HDI_RENDER_OFFSET_OFFLOAD = 6,
639     HDI_RENDER_OFFSET_MULTICHANNEL = 7,
640     HDI_RENDER_OFFSET_DIRECT = 8,
641     HDI_RENDER_OFFSET_VOIP = 9,
642     HDI_RENDER_OFFSET_DP = 10,
643     HDI_RENDER_OFFSET_USB = 11,
644     HDI_RENDER_OFFSET_VOIP_FAST = 12,
645 };
646 
647 uint32_t GenerateUniqueID(AudioHdiUniqueIDBase base, uint32_t offset);
648 
649 void CloseFd(int fd);
650 } // namespace AudioStandard
651 } // namespace OHOS
652 #endif // AUDIO_UTILS_H
653