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 
32 #include "audio_info.h"
33 #include "audio_common_utils.h"
34 
35 #define AUDIO_MS_PER_SECOND 1000
36 #define AUDIO_US_PER_SECOND 1000000
37 #define AUDIO_NS_PER_SECOND ((uint64_t)1000000000)
38 
39 #define FLOAT_EPS 1e-9f
40 #define OFFSET_BIT_24 3
41 #define BIT_DEPTH_TWO 2
42 #define BIT_8 8
43 #define BIT_16 16
44 #define BIT_24 24
45 #define BIT_32 32
46 namespace OHOS {
47 namespace AudioStandard {
48 const int64_t PCM_MAYBE_SILENT = 1;
49 const int64_t PCM_MAYBE_NOT_SILENT = 5;
50 const uint32_t MAX_VALUE_OF_SIGNED_24_BIT = 8388607;
51 const int32_t SIGNAL_DATA_SIZE = 96;
52 const int32_t SIGNAL_THRESHOLD = 10;
53 const int32_t BLANK_THRESHOLD_MS = 100;
54 const int32_t DETECTED_ZERO_THRESHOLD = 1;
55 const size_t MILLISECOND_PER_SECOND = 1000;
56 const size_t MOCK_INTERVAL = 2000;
57 const int32_t GET_EXTRA_PARAM_LEN = 200;
58 const int32_t YEAR_BASE = 1900;
59 const int32_t DECIMAL_EXPONENT = 10;
60 const size_t DATE_LENGTH = 17;
61 static uint32_t g_sessionToMock = 0;
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:
IsDualToneStreamType(const AudioStreamType streamType)75     static bool IsDualToneStreamType(const AudioStreamType streamType)
76     {
77         return streamType == STREAM_RING || streamType == STREAM_VOICE_RING || streamType == STREAM_ALARM;
78     }
79 
IsRingerOrAlarmerStreamUsage(const StreamUsage &usage)80     static bool IsRingerOrAlarmerStreamUsage(const StreamUsage &usage)
81     {
82         return usage == STREAM_USAGE_ALARM || usage == STREAM_USAGE_VOICE_RINGTONE || usage == STREAM_USAGE_RINGTONE;
83     }
84 
IsRingerAudioScene(const AudioScene &audioScene)85     static bool IsRingerAudioScene(const AudioScene &audioScene)
86     {
87         return audioScene == AUDIO_SCENE_RINGING || audioScene == AUDIO_SCENE_VOICE_RINGING;
88     }
89 };
90 
91 class Trace {
92 public:
93     static void Count(const std::string &value, int64_t count);
94     // Show if data is silent.
95     static void CountVolume(const std::string &value, uint8_t data);
96     Trace(const std::string &value);
97     void End();
98     ~Trace();
99 private:
100     std::string value_;
101     bool isFinished_;
102 };
103 
104 class AudioXCollie {
105 public:
106     AudioXCollie(const std::string &tag, uint32_t timeoutSeconds,
107         std::function<void(void *)> func = nullptr, void *arg = nullptr, uint32_t flag = 1);
108     ~AudioXCollie();
109     void CancelXCollieTimer();
110 private:
111     int32_t id_;
112     std::string tag_;
113     bool isCanceled_;
114 };
115 
116 class ClockTime {
117 public:
118     static int64_t GetCurNano();
119     static int32_t AbsoluteSleep(int64_t nanoTime);
120     static int32_t RelativeSleep(int64_t nanoTime);
121 };
122 
123 class PermissionUtil {
124 public:
125     static bool VerifyIsAudio();
126     static bool VerifyIsShell();
127     static bool VerifyIsSystemApp();
128     static bool VerifySelfPermission();
129     static bool VerifySystemPermission();
130     static bool VerifyPermission(const std::string &permissionName, uint32_t tokenId);
131     static bool NeedVerifyBackgroundCapture(int32_t callingUid, SourceType sourceType);
132     static bool VerifyBackgroundCapture(uint32_t tokenId, uint64_t fullTokenId);
133     static bool NotifyPrivacy(uint32_t targetTokenId, AudioPermissionState state);
134 };
135 
136 void AdjustStereoToMonoForPCM8Bit(int8_t *data, uint64_t len);
137 void AdjustStereoToMonoForPCM16Bit(int16_t *data, uint64_t len);
138 void AdjustStereoToMonoForPCM24Bit(uint8_t *data, uint64_t len);
139 void AdjustStereoToMonoForPCM32Bit(int32_t *data, uint64_t len);
140 void AdjustAudioBalanceForPCM8Bit(int8_t *data, uint64_t len, float left, float right);
141 void AdjustAudioBalanceForPCM16Bit(int16_t *data, uint64_t len, float left, float right);
142 void AdjustAudioBalanceForPCM24Bit(uint8_t *data, uint64_t len, float left, float right);
143 void AdjustAudioBalanceForPCM32Bit(int32_t *data, uint64_t len, float left, float right);
144 
145 void ConvertFrom24BitToFloat(unsigned n, const uint8_t *a, float *b);
146 void ConvertFrom32BitToFloat(unsigned n, const int32_t *a, float *b);
147 void ConvertFromFloatTo24Bit(unsigned n, const float *a, uint8_t *b);
148 void ConvertFromFloatTo32Bit(unsigned n, const float *a, int32_t *b);
149 
150 std::string GetEncryptStr(const std::string &str);
151 std::string ConvertNetworkId(const std::string &networkId);
152 
153 enum ConvertHdiFormat {
154     SAMPLE_U8_C = 0,
155     SAMPLE_S16_C = 1,
156     SAMPLE_S24_C = 2,
157     SAMPLE_S32_C = 3,
158     SAMPLE_F32_C = 4,
159     INVALID_WIDTH_C = -1
160 }; // same with HdiAdapterFormat
161 
162 float UpdateMaxAmplitude(ConvertHdiFormat adapterFormat, char *frame, uint64_t replyBytes);
163 float CalculateMaxAmplitudeForPCM8Bit(int8_t *frame, uint64_t nSamples);
164 float CalculateMaxAmplitudeForPCM16Bit(int16_t *frame, uint64_t nSamples);
165 float CalculateMaxAmplitudeForPCM24Bit(char *frame, uint64_t nSamples);
166 float CalculateMaxAmplitudeForPCM32Bit(int32_t *frame, uint64_t nSamples);
167 
168 template <typename T>
isEqual(T a, T b, double precision = 0.01)169 bool isEqual(T a, T b, double precision = 0.01)
170 {
171     return std::abs(a - b) < precision;
172 }
173 
174 // return true if value is not in the array.
175 template <typename V>
NotContain(const std::vector<V> &array, const V &value)176 inline bool NotContain(const std::vector<V> &array, const V &value)
177 {
178     return std::find(array.begin(), array.end(), value) == array.end();
179 }
180 
181 template <typename T>
182 bool GetSysPara(const char *key, T &value);
183 
184 enum AudioDumpFileType {
185     AUDIO_APP = 0,
186     OTHER_NATIVE_SERVICE = 1,
187     AUDIO_PULSE = 2,
188 };
189 
190 const std::string DUMP_SERVER_PARA = "sys.audio.dump.writeserver.enable";
191 const std::string DUMP_CLIENT_PARA = "sys.audio.dump.writeclient.enable";
192 const std::string DUMP_PULSE_DIR = "/data/data/.pulse_dir/";
193 const std::string DUMP_SERVICE_DIR = "/data/local/tmp/";
194 const std::string DUMP_APP_DIR = "/data/storage/el2/base/cache/";
195 const std::string DUMP_BLUETOOTH_RENDER_SINK_FILENAME = "dump_bluetooth_audiosink.pcm";
196 const std::string DUMP_RENDER_SINK_FILENAME = "dump_audiosink.pcm";
197 const std::string DUMP_MCH_SINK_FILENAME = "dump_mchaudiosink.pcm";
198 const std::string DUMP_DIRECT_RENDER_SINK_FILENAME = "dump_direct_audiosink.pcm";
199 const std::string DUMP_OFFLOAD_RENDER_SINK_FILENAME = "dump_offloadaudiosink.pcm";
200 const std::string DUMP_CAPTURER_SOURCE_FILENAME = "dump_capture_audiosource.pcm";
201 const std::string DUMP_TONEPLAYER_FILENAME = "dump_toneplayer_audio.pcm";
202 const std::string DUMP_PROCESS_IN_CLIENT_FILENAME = "dump_process_client_audio.pcm";
203 const std::string DUMP_REMOTE_RENDER_SINK_FILENAME = "dump_remote_audiosink";
204 const std::string DUMP_REMOTE_CAPTURE_SOURCE_FILENAME = "dump_remote_capture_audiosource.pcm";
205 const std::string DUMP_ENDPOINT_DCP_FILENAME = "dump_endpoint_dcp_audio.pcm";
206 const std::string DUMP_ENDPOINT_HDI_FILENAME = "dump_endpoint_hdi_audio.pcm";
207 const uint32_t PARAM_VALUE_LENTH = 150;
208 const std::string BETA_VERSION = "beta";
209 
210 class DumpFileUtil {
211 public:
212     static void WriteDumpFile(FILE *dumpFile, void *buffer, size_t bufferSize);
213     static void CloseDumpFile(FILE **dumpFile);
214     static std::map<std::string, std::string> g_lastPara;
215     static void OpenDumpFile(std::string para, std::string fileName, FILE **file);
216 private:
217     static FILE *OpenDumpFileInner(std::string para, std::string fileName, AudioDumpFileType fileType);
218     static void ChangeDumpFileState(std::string para, FILE **dumpFile, std::string fileName);
219 };
220 
221 template <typename...Args>
AppendFormat(std::string& out, const char* fmt, Args&& ... args)222 void AppendFormat(std::string& out, const char* fmt, Args&& ... args)
223 {
224     char buf[STRING_BUFFER_SIZE] = {0};
225     int len = ::sprintf_s(buf, sizeof(buf), fmt, args...);
226     if (len <= 0) {
227         return;
228     }
229     out += buf;
230 }
231 
232 class AudioInfoDumpUtils {
233 public:
234     static const std::string GetStreamName(AudioStreamType streamType);
235     static const std::string GetDeviceTypeName(DeviceType deviceType);
236     static const std::string GetConnectTypeName(ConnectType connectType);
237     static const std::string GetSourceName(SourceType sourceType);
238     static const std::string GetDeviceVolumeTypeName(DeviceVolumeType deviceType);
239 };
240 
241 template<typename T>
242 class ObjectRefMap {
243 public:
244     static std::mutex allObjLock;
245     static std::map<T*, uint32_t> refMap;
246     static void Insert(T *obj);
247     static void Erase(T *obj);
248     static T *IncreaseRef(T *obj);
249     static void DecreaseRef(T *obj);
250 
251     ObjectRefMap(T *obj);
252     ~ObjectRefMap();
253     T *GetPtr();
254 
255 private:
256     T *obj_ = nullptr;
257 };
258 
259 template <typename T>
260 std::mutex ObjectRefMap<T>::allObjLock;
261 
262 template <typename T>
263 std::map<T *, uint32_t> ObjectRefMap<T>::refMap;
264 
265 template <typename T>
Insert(T *obj)266 void ObjectRefMap<T>::Insert(T *obj)
267 {
268     std::lock_guard<std::mutex> lock(allObjLock);
269     refMap[obj] = 1;
270 }
271 
272 template <typename T>
Erase(T *obj)273 void ObjectRefMap<T>::Erase(T *obj)
274 {
275     std::lock_guard<std::mutex> lock(allObjLock);
276     auto it = refMap.find(obj);
277     if (it != refMap.end()) {
278         refMap.erase(it);
279     }
280 }
281 
282 template <typename T>
IncreaseRef(T *obj)283 T *ObjectRefMap<T>::IncreaseRef(T *obj)
284 {
285     std::lock_guard<std::mutex> lock(allObjLock);
286     if (refMap.count(obj)) {
287         refMap[obj]++;
288         return obj;
289     } else {
290         return nullptr;
291     }
292 }
293 
294 template <typename T>
DecreaseRef(T *obj)295 void ObjectRefMap<T>::DecreaseRef(T *obj)
296 {
297     std::lock_guard<std::mutex> lock(allObjLock);
298     if (refMap.count(obj) && --refMap[obj] == 0) {
299         refMap.erase(obj);
300         delete obj;
301         obj = nullptr;
302     }
303 }
304 
305 template <typename T>
ObjectRefMap(T *obj)306 ObjectRefMap<T>::ObjectRefMap(T *obj)
307 {
308     if (obj != nullptr) {
309         obj_ = ObjectRefMap::IncreaseRef(obj);
310     }
311 }
312 
313 template <typename T>
~ObjectRefMap()314 ObjectRefMap<T>::~ObjectRefMap()
315 {
316     if (obj_ != nullptr) {
317         ObjectRefMap::DecreaseRef(obj_);
318     }
319 }
320 
321 template <typename T>
GetPtr()322 T *ObjectRefMap<T>::GetPtr()
323 {
324     return obj_;
325 }
326 
327 std::string GetTime();
328 
329 int32_t GetFormatByteSize(int32_t format);
330 
331 struct SignalDetectAgent {
332     bool CheckAudioData(uint8_t *buffer, size_t bufferLen);
333     bool DetectSignalData(int32_t *buffer, size_t bufferLen);
334     void ResetDetectResult();
335     int32_t channels_ = STEREO;
336     int32_t sampleRate_ = SAMPLE_RATE_48000;
337     int32_t sampleFormat_ = SAMPLE_S16LE;
338     int32_t formatByteSize_;
339     int32_t lastPeakSignal_ = SHRT_MIN;
340     int32_t lastPeakSignalPos_ = 0;
341     int32_t blankPeriod_ = 0;
342     size_t frameCountIgnoreChannel_;
343     bool hasFirstNoneZero_ = false;
344     bool blankHaveOutput_ = true;
345     bool dspTimestampGot_ = false;
346     bool signalDetected_ = false;
347     std::string lastPeakBufferTime_ = "";
348     std::vector<int32_t> cacheAudioData_;
349 };
350 
351 class AudioLatencyMeasurement {
352 public:
353     // static methods, invoked without instantiation in sinks and sources
354     static bool CheckIfEnabled();
355     AudioLatencyMeasurement(const int32_t &sampleRate, const int32_t &channelCount,
356         const int32_t &sampleFormat, const std::string &appName, const uint32_t &sessionId);
357     ~AudioLatencyMeasurement();
358 
359     // non-static methods, invoked after instantiation in AudioRenderer and AudioCapturer
360     void InitSignalData();
361     bool MockPcmData(uint8_t *buffer, size_t bufferLen); // mute data and insert signal data
362 private:
363     int32_t format_ = SAMPLE_S16LE;
364     int32_t formatByteSize_;
365     int32_t sampleRate_;
366     int32_t channelCount_;
367     uint32_t sessionId_;
368     size_t mockedTime_ = 0;
369     bool mockThisStream_ = false;
370     std::string appName_;
371     std::unique_ptr<int16_t[]> signalData_ = nullptr;
372 };
373 
374 class LatencyMonitor {
375 public:
376     static LatencyMonitor& GetInstance();
377     void ShowTimestamp(bool isRenderer);
378     void ShowBluetoothTimestamp();
379     void UpdateClientTime(bool isRenderer, std::string &timestamp);
380     void UpdateSinkOrSourceTime(bool isRenderer, std::string &timestamp);
381     void UpdateDspTime(std::string dspTime);
382 private:
383     std::string rendererMockTime_ = "";
384     std::string sinkDetectedTime_ = "";
385     std::string dspDetectedTime_ = "";
386     std::string capturerDetectedTime_ = "";
387     std::string sourceDetectedTime_ = "";
388     std::string dspBeforeSmartPa_ = "";
389     std::string dspAfterSmartPa_ = "";
390     std::string dspMockTime_ = "";
391     size_t extraStrLen_ = 0;
392 };
393 
394 class AudioDump {
395 public:
396     static AudioDump& GetInstance();
397     void SetVersionType(const std::string& versionType);
398     std::string GetVersionType();
399 private:
AudioDump()400     AudioDump() {}
~AudioDump()401     ~AudioDump() {}
402     std::string versionType_ = "commercial";
403 };
404 
405 template <typename EnumType, typename V>
GetKeyFromValue(const std::unordered_map<EnumType, V> &map, const V &value)406 int32_t GetKeyFromValue(const std::unordered_map<EnumType, V> &map, const V &value)
407 {
408     for (auto it : map) {
409         if (it.second == value) {
410             return it.first;
411         }
412     }
413     return -1;
414 }
415 
416 template <typename T, typename Compare>
CasWithCompare(std::atomic<T> &atomicVar, T newValue, Compare compare)417 bool CasWithCompare(std::atomic<T> &atomicVar, T newValue, Compare compare)
418 {
419     T old = atomicVar;
420     do {
421         if (!compare(old, newValue)) {
422             return false;
423         }
424     } while (!atomicVar.compare_exchange_weak(old, newValue));
425 
426     return true;
427 }
428 
429 /**
430  * @brief Provides interfaces for thread-safe blocking queues.
431  *
432  * The interfaces can be used to perform blocking and non-blocking push and
433  * pop operations on queues.
434  */
435 template <typename T>
436 class AudioSafeBlockQueue {
437 public:
AudioSafeBlockQueue(int capacity)438     explicit AudioSafeBlockQueue(int capacity) : maxSize_(capacity)
439     {
440     }
441 
442     /**
443      * @brief Inserts an element at the end of this queue in blocking mode.
444      *
445      * If the queue is full, the thread of the push operation will be blocked
446      * until the queue has space.
447      * If the queue is not full, the push operation can be performed and one of the
448      * pop threads (blocked when the queue is empty) is woken up.
449      *
450      * @param elem Indicates the element to insert.
451      */
Push(T const& elem)452     virtual void Push(T const& elem)
453     {
454         std::unique_lock<std::mutex> lock(mutexLock_);
455         while (queueT_.size() >= maxSize_) {
456             // If the queue is full, wait for jobs to be taken.
457             cvNotFull_.wait(lock, [&]() { return (queueT_.size() < maxSize_); });
458         }
459 
460         // Insert the element into the queue if the queue is not full.
461         queueT_.push(elem);
462         cvNotEmpty_.notify_all();
463     }
464 
465     /**
466      * @brief Removes the first element from this queue in blocking mode.
467      *
468      * If the queue is empty, the thread of the pop operation will be blocked
469      * until the queue has elements.
470      * If the queue is not empty, the pop operation can be performed, the first
471      * element of the queue is returned, and one of the push threads (blocked
472      * when the queue is full) is woken up.
473      */
Pop()474     T Pop()
475     {
476         std::unique_lock<std::mutex> lock(mutexLock_);
477 
478         while (queueT_.empty()) {
479             // If the queue is empty, wait for elements to be pushed in.
480             cvNotEmpty_.wait(lock, [&] { return !queueT_.empty(); });
481         }
482 
483         T elem = queueT_.front();
484         queueT_.pop();
485         cvNotFull_.notify_all();
486         return elem;
487     }
488 
489     /**
490      * @brief Inserts an element at the end of this queue in non-blocking mode.
491      *
492      * If the queue is full, <b>false</b> is returned directly.
493      * If the queue is not full, the push operation can be performed, one of the
494      * pop threads (blocked when the queue is empty) is woken up, and <b>true</b>
495      * is returned.
496      *
497      * @param elem Indicates the element to insert.
498      */
PushNoWait(T const& elem)499     virtual bool PushNoWait(T const& elem)
500     {
501         std::unique_lock<std::mutex> lock(mutexLock_);
502         if (queueT_.size() >= maxSize_) {
503             return false;
504         }
505         // Insert the element if the queue is not full.
506         queueT_.push(elem);
507         cvNotEmpty_.notify_all();
508         return true;
509     }
510 
511     /**
512      * @brief Removes the first element from this queue in non-blocking mode.
513      *
514      * If the queue is empty, <b>false</b> is returned directly.
515      * If the queue is not empty, the pop operation can be performed, one of the
516      * push threads (blocked when the queue is full) is woken up, and <b>true</b>
517      * is returned.
518      *
519      * @param outtask Indicates the data of the pop operation.
520      */
PopNotWait(T& outtask)521     bool PopNotWait(T& outtask)
522     {
523         std::unique_lock<std::mutex> lock(mutexLock_);
524         if (queueT_.empty()) {
525             return false;
526         }
527         outtask = queueT_.front();
528         queueT_.pop();
529 
530         cvNotFull_.notify_all();
531 
532         return true;
533     }
534 
PopAllNotWait()535     std::queue<T> PopAllNotWait()
536     {
537         std::queue<T> retQueue = {};
538         std::unique_lock<std::mutex> lock(mutexLock_);
539         retQueue.swap(queueT_);
540 
541         cvNotFull_.notify_all();
542 
543         return retQueue;
544     }
545 
Size()546     unsigned int Size()
547     {
548         std::unique_lock<std::mutex> lock(mutexLock_);
549         return queueT_.size();
550     }
551 
552     template< class Rep, class Period >
WaitNotEmptyFor(const std::chrono::duration<Rep, Period>& rel_time)553     void WaitNotEmptyFor(const std::chrono::duration<Rep, Period>& rel_time)
554     {
555         std::unique_lock<std::mutex> lock(mutexLock_);
556         cvNotEmpty_.wait_for(lock, rel_time, [this] {
557             return !queueT_.empty();
558         });
559     }
560 
IsEmpty()561     bool IsEmpty()
562     {
563         std::unique_lock<std::mutex> lock(mutexLock_);
564         return queueT_.empty();
565     }
566 
IsFull()567     bool IsFull()
568     {
569         std::unique_lock<std::mutex> lock(mutexLock_);
570         return queueT_.size() == maxSize_;
571     }
572 
Clear()573     void Clear()
574     {
575         std::unique_lock<std::mutex> lock(mutexLock_);
576         queueT_ = {};
577         cvNotFull_.notify_all();
578     }
579 
~AudioSafeBlockQueue()580     virtual ~AudioSafeBlockQueue() {}
581 
582 protected:
583     unsigned long maxSize_;  // Capacity of the queue
584     std::mutex mutexLock_;
585     std::condition_variable cvNotEmpty_;
586     std::condition_variable cvNotFull_;
587     std::queue<T> queueT_;
588 };
589 
590 enum AudioHdiUniqueIDBase : uint32_t {
591     // 0-4 is reserved for other modules
592     AUDIO_HDI_RENDER_ID_BASE = 5,
593     AUDIO_HDI_CAPTURE_ID_BASE = 6,
594 };
595 
596 enum HdiCaptureOffset : uint32_t {
597     HDI_CAPTURE_OFFSET_PRIMARY = 1,
598     HDI_CAPTURE_OFFSET_FAST = 2,
599     HDI_CAPTURE_OFFSET_REMOTE = 3,
600     HDI_CAPTURE_OFFSET_REMOTE_FAST = 4,
601     HDI_CAPTURE_OFFSET_USB = 5,
602     HDI_CAPTURE_OFFSET_EC = 6,
603     HDI_CAPTURE_OFFSET_MIC_REF = 7,
604     HDI_CAPTURE_OFFSET_WAKEUP = 8,
605 };
606 
607 enum HdiRenderOffset : uint32_t {
608     HDI_RENDER_OFFSET_PRIMARY = 1,
609     HDI_RENDER_OFFSET_FAST = 2,
610     HDI_RENDER_OFFSET_REMOTE = 3,
611     HDI_RENDER_OFFSET_REMOTE_FAST = 4,
612     HDI_RENDER_OFFSET_BLUETOOTH = 5,
613     HDI_RENDER_OFFSET_OFFLOAD = 6,
614     HDI_RENDER_OFFSET_MULTICHANNEL = 7,
615     HDI_RENDER_OFFSET_DIRECT = 8,
616     HDI_RENDER_OFFSET_VOIP = 9,
617     HDI_RENDER_OFFSET_DP = 10,
618     HDI_RENDER_OFFSET_USB = 11,
619     HDI_RENDER_OFFSET_VOIP_FAST = 12,
620 };
621 
622 uint32_t GenerateUniqueID(AudioHdiUniqueIDBase base, uint32_t offset);
623 
624 } // namespace AudioStandard
625 } // namespace OHOS
626 #endif // AUDIO_UTILS_H
627