• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 LOG_TAG
16 #define LOG_TAG "OHAudioBufferBase"
17 #endif
18 
19 #include "oh_audio_buffer.h"
20 
21 #include <cinttypes>
22 #include <climits>
23 #include <memory>
24 #include <sys/mman.h>
25 #include "ashmem.h"
26 
27 #include "audio_errors.h"
28 #include "audio_service_log.h"
29 #include "futex_tool.h"
30 #include "audio_utils.h"
31 #include "audio_parcel_helper.h"
32 
33 namespace OHOS {
34 namespace AudioStandard {
35 namespace {
36     static const size_t MAX_MMAP_BUFFER_SIZE = 10 * 1024 * 1024; // 10M
37     static const std::string STATUS_INFO_BUFFER = "status_info_buffer";
38     static constexpr int MINFD = 2;
39 }
40 class AudioSharedMemoryImpl : public AudioSharedMemory {
41 public:
42     uint8_t *GetBase() override;
43     size_t GetSize() override;
44     int GetFd() override;
45     std::string GetName() override;
46 
47     AudioSharedMemoryImpl(size_t size, const std::string &name);
48 
49     AudioSharedMemoryImpl(int fd, size_t size, const std::string &name);
50 
51     ~AudioSharedMemoryImpl();
52 
53     int32_t Init();
54 
55     bool Marshalling(Parcel &parcel) const override;
56 
57 private:
58     void Close();
59 
60     uint8_t *base_;
61     int fd_;
62     size_t size_;
63     std::string name_;
64 };
65 
66 class ScopedFd {
67 public:
ScopedFd(int fd)68     explicit ScopedFd(int fd) : fd_(fd) {}
~ScopedFd()69     ~ScopedFd()
70     {
71         if (fd_ > MINFD) {
72             CloseFd(fd_);
73         }
74     }
75 private:
76     int fd_ = -1;
77 };
78 
AudioSharedMemoryImpl(size_t size,const std::string & name)79 AudioSharedMemoryImpl::AudioSharedMemoryImpl(size_t size, const std::string &name)
80     : base_(nullptr), fd_(INVALID_FD), size_(size), name_(name)
81 {
82     AUDIO_DEBUG_LOG("AudioSharedMemory ctor with size: %{public}zu name: %{public}s", size_, name_.c_str());
83 }
84 
AudioSharedMemoryImpl(int fd,size_t size,const std::string & name)85 AudioSharedMemoryImpl::AudioSharedMemoryImpl(int fd, size_t size, const std::string &name)
86     : base_(nullptr), fd_(dup(fd)), size_(size), name_(name)
87 {
88     AUDIO_DEBUG_LOG("AudioSharedMemory ctor with fd %{public}d size %{public}zu name %{public}s", fd_, size_,
89         name_.c_str());
90 }
91 
~AudioSharedMemoryImpl()92 AudioSharedMemoryImpl::~AudioSharedMemoryImpl()
93 {
94     AUDIO_DEBUG_LOG(" %{public}s enter ~AudioSharedMemoryImpl()", name_.c_str());
95     Close();
96 }
97 
Init()98 int32_t AudioSharedMemoryImpl::Init()
99 {
100     CHECK_AND_RETURN_RET_LOG((size_ > 0 && size_ < MAX_MMAP_BUFFER_SIZE), ERR_INVALID_PARAM,
101         "Init falied: size out of range: %{public}zu", size_);
102     bool isFromRemote = false;
103     if (fd_ >= 0) {
104         if (fd_ == STDIN_FILENO || fd_ == STDOUT_FILENO || fd_ == STDERR_FILENO) {
105             AUDIO_WARNING_LOG("fd is special fd: %{public}d", fd_);
106         }
107         isFromRemote = true;
108         int size = AshmemGetSize(fd_); // hdi fd may not support
109         if (size < 0 || static_cast<size_t>(size) != size_) {
110             AUDIO_WARNING_LOG("AshmemGetSize faied, get %{public}d", size);
111         }
112     } else {
113         fd_ = AshmemCreate(name_.c_str(), size_);
114         if (fd_ == STDIN_FILENO || fd_ == STDOUT_FILENO || fd_ == STDERR_FILENO) {
115             AUDIO_WARNING_LOG("fd is special fd: %{public}d", fd_);
116         }
117         CHECK_AND_RETURN_RET_LOG((fd_ >= 0), ERR_OPERATION_FAILED, "Init falied: fd %{public}d", fd_);
118     }
119 
120     void *addr = mmap(nullptr, size_, PROT_READ | PROT_WRITE, MAP_SHARED, fd_, 0);
121     CHECK_AND_RETURN_RET_LOG(addr != MAP_FAILED, ERR_OPERATION_FAILED, "Init falied: fd %{public}d size %{public}zu",
122         fd_, size_);
123     base_ = static_cast<uint8_t *>(addr);
124     AUDIO_DEBUG_LOG("Init %{public}s <%{public}s> done.", (isFromRemote ? "remote" : "local"),
125         name_.c_str());
126     return SUCCESS;
127 }
128 
Marshalling(Parcel & parcel) const129 bool AudioSharedMemoryImpl::Marshalling(Parcel &parcel) const
130 {
131     // Parcel -> MessageParcel
132     MessageParcel &msgParcel = static_cast<MessageParcel &>(parcel);
133     CHECK_AND_RETURN_RET_LOG((size_ > 0 && size_ < MAX_MMAP_BUFFER_SIZE), false, "invalid size: %{public}zu", size_);
134     return msgParcel.WriteFileDescriptor(fd_) &&
135         msgParcel.WriteUint64(static_cast<uint64_t>(size_)) &&
136         msgParcel.WriteString(name_);
137 }
138 
Close()139 void AudioSharedMemoryImpl::Close()
140 {
141     if (base_ != nullptr) {
142         (void)munmap(base_, size_);
143         base_ = nullptr;
144         size_ = 0;
145         AUDIO_DEBUG_LOG("%{public}s munmap done", name_.c_str());
146     }
147 
148     if (fd_ >= 0) {
149         (void)CloseFd(fd_);
150         fd_ = INVALID_FD;
151         AUDIO_DEBUG_LOG("%{public}s close fd done", name_.c_str());
152     }
153 }
154 
GetBase()155 uint8_t *AudioSharedMemoryImpl::GetBase()
156 {
157     return base_;
158 }
159 
GetSize()160 size_t AudioSharedMemoryImpl::GetSize()
161 {
162     return size_;
163 }
164 
GetName()165 std::string AudioSharedMemoryImpl::GetName()
166 {
167     return name_;
168 }
169 
GetFd()170 int AudioSharedMemoryImpl::GetFd()
171 {
172     return fd_;
173 }
174 
CreateFormLocal(size_t size,const std::string & name)175 std::shared_ptr<AudioSharedMemory> AudioSharedMemory::CreateFormLocal(size_t size, const std::string &name)
176 {
177     std::shared_ptr<AudioSharedMemoryImpl> sharedMemory = std::make_shared<AudioSharedMemoryImpl>(size, name);
178     CHECK_AND_RETURN_RET_LOG(sharedMemory->Init() == SUCCESS,
179         nullptr, "CreateFormLocal failed");
180     return sharedMemory;
181 }
182 
CreateFromRemote(int fd,size_t size,const std::string & name)183 std::shared_ptr<AudioSharedMemory> AudioSharedMemory::CreateFromRemote(int fd, size_t size, const std::string &name)
184 {
185     int minfd = 2; // ignore stdout, stdin and stderr.
186     CHECK_AND_RETURN_RET_LOG(fd > minfd, nullptr, "CreateFromRemote failed: invalid fd: %{public}d", fd);
187     std::shared_ptr<AudioSharedMemoryImpl> sharedMemory = std::make_shared<AudioSharedMemoryImpl>(fd, size, name);
188     if (sharedMemory->Init() != SUCCESS) {
189         AUDIO_ERR_LOG("CreateFromRemote failed");
190         return nullptr;
191     }
192     return sharedMemory;
193 }
194 
WriteToParcel(const std::shared_ptr<AudioSharedMemory> & memory,MessageParcel & parcel)195 int32_t AudioSharedMemory::WriteToParcel(const std::shared_ptr<AudioSharedMemory> &memory, MessageParcel &parcel)
196 {
197     std::shared_ptr<AudioSharedMemoryImpl> memoryImpl = std::static_pointer_cast<AudioSharedMemoryImpl>(memory);
198     CHECK_AND_RETURN_RET_LOG(memoryImpl != nullptr, ERR_OPERATION_FAILED, "invalid pointer.");
199 
200     int32_t fd = memoryImpl->GetFd();
201 
202     size_t size = memoryImpl->GetSize();
203     CHECK_AND_RETURN_RET_LOG((size > 0 && size < MAX_MMAP_BUFFER_SIZE), ERR_INVALID_PARAM,
204         "invalid size: %{public}zu", size);
205     uint64_t sizeTmp = static_cast<uint64_t>(size);
206 
207     std::string name = memoryImpl->GetName();
208 
209     parcel.WriteFileDescriptor(fd);
210     parcel.WriteUint64(sizeTmp);
211     parcel.WriteString(name);
212 
213     return SUCCESS;
214 }
215 
ReadFromParcel(MessageParcel & parcel)216 std::shared_ptr<AudioSharedMemory> AudioSharedMemory::ReadFromParcel(MessageParcel &parcel)
217 {
218     int fd = parcel.ReadFileDescriptor();
219 
220     uint64_t sizeTmp = parcel.ReadUint64();
221     CHECK_AND_RETURN_RET_LOG((sizeTmp > 0 && sizeTmp < MAX_MMAP_BUFFER_SIZE), nullptr, "failed with invalid size");
222     size_t size = static_cast<size_t>(sizeTmp);
223 
224     std::string name = parcel.ReadString();
225 
226     std::shared_ptr<AudioSharedMemory> memory = AudioSharedMemory::CreateFromRemote(fd, size, name);
227     if (memory == nullptr || memory->GetBase() == nullptr) {
228         AUDIO_ERR_LOG("ReadFromParcel failed");
229         memory = nullptr;
230     }
231     CloseFd(fd);
232     return memory;
233 }
234 
Marshalling(Parcel & parcel) const235 bool AudioSharedMemory::Marshalling(Parcel &parcel) const
236 {
237     return true;
238 }
239 
Unmarshalling(Parcel & parcel)240 AudioSharedMemory *AudioSharedMemory::Unmarshalling(Parcel &parcel)
241 {
242     // Parcel -> MessageParcel
243     MessageParcel &msgParcel = static_cast<MessageParcel &>(parcel);
244     int fd = msgParcel.ReadFileDescriptor();
245     int minfd = 2; // ignore stdout, stdin and stderr.
246     CHECK_AND_RETURN_RET_LOG(fd > minfd, nullptr, "CreateFromRemote failed: invalid fd: %{public}d", fd);
247     ScopedFd scopedFd(fd);
248 
249     uint64_t sizeTmp = msgParcel.ReadUint64();
250     CHECK_AND_RETURN_RET_LOG((sizeTmp > 0 && sizeTmp < MAX_MMAP_BUFFER_SIZE), nullptr, "failed with invalid size");
251     size_t size = static_cast<size_t>(sizeTmp);
252 
253     std::string name = msgParcel.ReadString();
254 
255     auto memory = new(std::nothrow) AudioSharedMemoryImpl(fd, size, name);
256     if (memory == nullptr) {
257         AUDIO_ERR_LOG("not enough memory");
258         return nullptr;
259     }
260 
261     if (memory->Init() != SUCCESS || memory->GetBase() == nullptr) {
262         AUDIO_ERR_LOG("Init failed or GetBase failed");
263         delete memory;
264         return nullptr;
265     }
266     return memory;
267 }
268 
OHAudioBufferBase(AudioBufferHolder bufferHolder,uint32_t totalSizeInFrame,uint32_t byteSizePerFrame)269 OHAudioBufferBase::OHAudioBufferBase(AudioBufferHolder bufferHolder, uint32_t totalSizeInFrame,
270     uint32_t byteSizePerFrame) : bufferHolder_(bufferHolder), totalSizeInFrame_(totalSizeInFrame),
271     byteSizePerFrame_(byteSizePerFrame), totalSizeInByte_(totalSizeInFrame * byteSizePerFrame),
272     audioMode_(AUDIO_MODE_PLAYBACK),
273     basicBufferInfo_(nullptr)
274 {
275     AUDIO_DEBUG_LOG("ctor with holder:%{public}d mode:%{public}d", bufferHolder_, audioMode_);
276 }
277 
SizeCheck()278 int32_t OHAudioBufferBase::SizeCheck()
279 {
280     if (totalSizeInFrame_ > UINT_MAX / byteSizePerFrame_) {
281         AUDIO_ERR_LOG("failed: totalSizeInFrame: %{public}u byteSizePerFrame: %{public}u",
282             totalSizeInFrame_, byteSizePerFrame_);
283         return ERR_INVALID_PARAM;
284     }
285 
286     // data buffer size check
287     CHECK_AND_RETURN_RET_LOG((totalSizeInByte_ < MAX_MMAP_BUFFER_SIZE), ERR_INVALID_PARAM, "too large totalSizeInByte "
288         "%{public}zu", totalSizeInByte_);
289 
290     return SUCCESS;
291 }
292 
Init(int dataFd,int infoFd,size_t statusInfoExtSize)293 int32_t OHAudioBufferBase::Init(int dataFd, int infoFd, size_t statusInfoExtSize)
294 {
295     int32_t ret = SizeCheck();
296     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_INVALID_PARAM, "failed: invalid size.");
297 
298     // init for statusInfoBuffer
299     size_t statusInfoSize = sizeof(BasicBufferInfo) + statusInfoExtSize;
300     if (infoFd != INVALID_FD && (bufferHolder_ == AUDIO_CLIENT || bufferHolder_ == AUDIO_SERVER_INDEPENDENT)) {
301         statusInfoMem_ = AudioSharedMemory::CreateFromRemote(infoFd, statusInfoSize, STATUS_INFO_BUFFER);
302     } else {
303         statusInfoMem_ = AudioSharedMemory::CreateFormLocal(statusInfoSize, STATUS_INFO_BUFFER);
304     }
305     CHECK_AND_RETURN_RET_LOG(statusInfoMem_ != nullptr, ERR_OPERATION_FAILED, "BasicBufferInfo mmap failed.");
306 
307     // init for dataBuffer
308     if (dataFd == INVALID_FD && bufferHolder_ == AUDIO_SERVER_SHARED) {
309         dataMem_ = AudioSharedMemory::CreateFormLocal(totalSizeInByte_, "server_client_buffer");
310     } else {
311         std::string memoryDesc = (bufferHolder_ == AUDIO_SERVER_ONLY ? "server_hdi_buffer" : "server_client_buffer");
312         if (bufferHolder_ == AUDIO_SERVER_ONLY_WITH_SYNC) {
313             AUDIO_INFO_LOG("Init sever_hdi_buffer with sync info");
314             dataMem_ = AudioSharedMemory::CreateFromRemote(dataFd, totalSizeInByte_ + BASIC_SYNC_INFO_SIZE, memoryDesc);
315         } else { // AUDIO_SERVER_ONLY
316             dataMem_ = AudioSharedMemory::CreateFromRemote(dataFd, totalSizeInByte_, memoryDesc);
317         }
318     }
319     CHECK_AND_RETURN_RET_LOG(dataMem_ != nullptr, ERR_OPERATION_FAILED, "dataMem_ mmap failed.");
320     if (bufferHolder_ == AUDIO_SERVER_ONLY_WITH_SYNC) {
321         syncReadFrame_ = reinterpret_cast<uint32_t *>(dataMem_->GetBase() + totalSizeInByte_);
322         syncWriteFrame_ = syncReadFrame_ + sizeof(uint32_t);
323     }
324 
325     dataBase_ = dataMem_->GetBase();
326 
327     basicBufferInfo_ = reinterpret_cast<BasicBufferInfo *>(statusInfoMem_->GetBase());
328 
329     InitBasicBufferInfo();
330 
331     if (bufferHolder_ == AUDIO_SERVER_SHARED || bufferHolder_ == AUDIO_SERVER_ONLY || bufferHolder_ ==
332             AUDIO_SERVER_ONLY_WITH_SYNC) {
333         basicBufferInfo_->handlePos.store(0);
334         basicBufferInfo_->handleTime.store(0);
335         basicBufferInfo_->totalSizeInFrame = totalSizeInFrame_;
336         basicBufferInfo_->byteSizePerFrame = byteSizePerFrame_;
337         basicBufferInfo_->streamStatus.store(STREAM_INVALID);
338     }
339 
340     AUDIO_DEBUG_LOG("Init done.");
341     return SUCCESS;
342 }
343 
CreateFromLocal(uint32_t totalSizeInFrame,uint32_t byteSizePerFrame)344 std::shared_ptr<OHAudioBufferBase> OHAudioBufferBase::CreateFromLocal(uint32_t totalSizeInFrame,
345     uint32_t byteSizePerFrame)
346 {
347     AUDIO_DEBUG_LOG("totalSizeInFrame %{public}d, byteSizePerFrame"
348         " %{public}d", totalSizeInFrame, byteSizePerFrame);
349 
350     AudioBufferHolder bufferHolder = AudioBufferHolder::AUDIO_SERVER_SHARED;
351     std::shared_ptr<OHAudioBufferBase> buffer = std::make_shared<OHAudioBufferBase>(bufferHolder, totalSizeInFrame,
352         byteSizePerFrame);
353     CHECK_AND_RETURN_RET_LOG(buffer->Init(INVALID_FD, INVALID_FD, 0) == SUCCESS,
354         nullptr, "failed to init.");
355     return buffer;
356 }
357 
CreateFromRemote(uint32_t totalSizeInFrame,uint32_t byteSizePerFrame,AudioBufferHolder bufferHolder,int dataFd,int infoFd)358 std::shared_ptr<OHAudioBufferBase> OHAudioBufferBase::CreateFromRemote(uint32_t totalSizeInFrame,
359     uint32_t byteSizePerFrame, AudioBufferHolder bufferHolder,
360     int dataFd, int infoFd)
361 {
362     AUDIO_DEBUG_LOG("dataFd %{public}d, infoFd %{public}d", dataFd, infoFd);
363 
364     int minfd = 2; // ignore stdout, stdin and stderr.
365     CHECK_AND_RETURN_RET_LOG(dataFd > minfd, nullptr, "invalid dataFd: %{public}d", dataFd);
366 
367     if (infoFd != INVALID_FD) {
368         CHECK_AND_RETURN_RET_LOG(infoFd > minfd, nullptr, "invalid infoFd: %{public}d", infoFd);
369     }
370     std::shared_ptr<OHAudioBufferBase> buffer = std::make_shared<OHAudioBufferBase>(bufferHolder, totalSizeInFrame,
371         byteSizePerFrame);
372     if (buffer->Init(dataFd, infoFd, 0) != SUCCESS) {
373         AUDIO_ERR_LOG("failed to init.");
374         return nullptr;
375     }
376     return buffer;
377 }
378 
WriteToParcel(const std::shared_ptr<OHAudioBufferBase> & buffer,MessageParcel & parcel)379 int32_t OHAudioBufferBase::WriteToParcel(const std::shared_ptr<OHAudioBufferBase> &buffer, MessageParcel &parcel)
380 {
381     AUDIO_DEBUG_LOG("WriteToParcel start.");
382     AudioBufferHolder bufferHolder = buffer->GetBufferHolder();
383     CHECK_AND_RETURN_RET_LOG(bufferHolder == AudioBufferHolder::AUDIO_SERVER_SHARED ||
384         bufferHolder == AudioBufferHolder::AUDIO_SERVER_INDEPENDENT,
385         ERROR_INVALID_PARAM, "buffer holder error:%{public}d", bufferHolder);
386 
387     auto initInfo = buffer->GetInitializationInfo();
388 
389     parcel.WriteUint32(bufferHolder);
390     parcel.WriteUint32(initInfo.totalSizeInFrame);
391     parcel.WriteUint32(initInfo.byteSizePerFrame);
392 
393     parcel.WriteFileDescriptor(initInfo.dataFd);
394     parcel.WriteFileDescriptor(initInfo.infoFd);
395 
396     AUDIO_DEBUG_LOG("WriteToParcel done.");
397     return SUCCESS;
398 }
399 
ReadFromParcel(MessageParcel & parcel)400 std::shared_ptr<OHAudioBufferBase> OHAudioBufferBase::ReadFromParcel(MessageParcel &parcel)
401 {
402     AUDIO_DEBUG_LOG("ReadFromParcel start.");
403     uint32_t holder = parcel.ReadUint32();
404     AudioBufferHolder bufferHolder = static_cast<AudioBufferHolder>(holder);
405     if (bufferHolder != AudioBufferHolder::AUDIO_SERVER_SHARED &&
406         bufferHolder != AudioBufferHolder::AUDIO_SERVER_INDEPENDENT) {
407         AUDIO_ERR_LOG("ReadFromParcel buffer holder error:%{public}d", bufferHolder);
408         return nullptr;
409     }
410     bufferHolder = bufferHolder == AudioBufferHolder::AUDIO_SERVER_SHARED ?
411          AudioBufferHolder::AUDIO_CLIENT : bufferHolder;
412     uint32_t totalSizeInFrame = parcel.ReadUint32();
413     uint32_t byteSizePerFrame = parcel.ReadUint32();
414 
415     int dataFd = parcel.ReadFileDescriptor();
416     int infoFd = parcel.ReadFileDescriptor();
417 
418     std::shared_ptr<OHAudioBufferBase> buffer = OHAudioBufferBase::CreateFromRemote(totalSizeInFrame,
419         byteSizePerFrame, bufferHolder, dataFd, infoFd);
420     if (buffer == nullptr) {
421         AUDIO_ERR_LOG("ReadFromParcel failed.");
422     } else if (totalSizeInFrame != buffer->basicBufferInfo_->totalSizeInFrame ||
423         byteSizePerFrame != buffer->basicBufferInfo_->byteSizePerFrame) {
424         AUDIO_WARNING_LOG("data in shared memory diff.");
425     } else {
426         AUDIO_DEBUG_LOG("Read some data done.");
427     }
428     CloseFd(dataFd);
429     CloseFd(infoFd);
430     AUDIO_DEBUG_LOG("ReadFromParcel done.");
431     return buffer;
432 }
433 
Marshalling(Parcel & parcel) const434 bool OHAudioBufferBase::Marshalling(Parcel &parcel) const
435 {
436     MessageParcel &messageParcel = static_cast<MessageParcel &>(parcel);
437     AudioBufferHolder bufferHolder = bufferHolder_;
438     CHECK_AND_RETURN_RET_LOG(bufferHolder == AudioBufferHolder::AUDIO_SERVER_SHARED ||
439         bufferHolder == AudioBufferHolder::AUDIO_SERVER_INDEPENDENT,
440         false, "buffer holder error:%{public}d", bufferHolder);
441     CHECK_AND_RETURN_RET_LOG(dataMem_ != nullptr, false, "dataMem_ is nullptr.");
442     CHECK_AND_RETURN_RET_LOG(statusInfoMem_ != nullptr, false, "statusInfoMem_ is nullptr.");
443 
444     return messageParcel.WriteUint32(bufferHolder) &&
445         messageParcel.WriteUint32(totalSizeInFrame_) &&
446         messageParcel.WriteUint32(byteSizePerFrame_) &&
447         messageParcel.WriteFileDescriptor(dataMem_->GetFd()) &&
448         messageParcel.WriteFileDescriptor(statusInfoMem_->GetFd());
449 }
450 
Unmarshalling(Parcel & parcel)451 OHAudioBufferBase *OHAudioBufferBase::Unmarshalling(Parcel &parcel)
452 {
453     AUDIO_DEBUG_LOG("ReadFromParcel start.");
454     MessageParcel &messageParcel = static_cast<MessageParcel &>(parcel);
455     uint32_t holder = messageParcel.ReadUint32();
456     AudioBufferHolder bufferHolder = static_cast<AudioBufferHolder>(holder);
457     if (bufferHolder != AudioBufferHolder::AUDIO_SERVER_SHARED &&
458         bufferHolder != AudioBufferHolder::AUDIO_SERVER_INDEPENDENT) {
459         AUDIO_ERR_LOG("ReadFromParcel buffer holder error:%{public}d", bufferHolder);
460         return nullptr;
461     }
462     bufferHolder = bufferHolder == AudioBufferHolder::AUDIO_SERVER_SHARED ?
463          AudioBufferHolder::AUDIO_CLIENT : bufferHolder;
464     uint32_t totalSizeInFrame = messageParcel.ReadUint32();
465     uint32_t byteSizePerFrame = messageParcel.ReadUint32();
466 
467     int dataFd = messageParcel.ReadFileDescriptor();
468     int infoFd = messageParcel.ReadFileDescriptor();
469 
470     int minfd = 2; // ignore stdout, stdin and stderr.
471     CHECK_AND_RETURN_RET_LOG(dataFd > minfd, nullptr, "invalid dataFd: %{public}d", dataFd);
472 
473     if (infoFd != INVALID_FD) {
474         CHECK_AND_RETURN_RET_LOG(infoFd > minfd, nullptr, "invalid infoFd: %{public}d", infoFd);
475     }
476     auto buffer = new(std::nothrow) OHAudioBufferBase(bufferHolder, totalSizeInFrame, byteSizePerFrame);
477     if (buffer == nullptr || buffer->Init(dataFd, infoFd, 0) != SUCCESS || buffer->basicBufferInfo_ == nullptr) {
478         AUDIO_ERR_LOG("failed to init.");
479         if (buffer != nullptr) delete buffer;
480         CloseFd(dataFd);
481         CloseFd(infoFd);
482         return nullptr;
483     }
484 
485     if (totalSizeInFrame != buffer->basicBufferInfo_->totalSizeInFrame ||
486         byteSizePerFrame != buffer->basicBufferInfo_->byteSizePerFrame) {
487         AUDIO_WARNING_LOG("data in shared memory diff.");
488     } else {
489         AUDIO_DEBUG_LOG("Read some data done.");
490     }
491     CloseFd(dataFd);
492     CloseFd(infoFd);
493     AUDIO_DEBUG_LOG("ReadFromParcel done.");
494     return buffer;
495 }
496 
GetStatusInfoExtPtr()497 void* OHAudioBufferBase::GetStatusInfoExtPtr()
498 {
499     CHECK_AND_RETURN_RET_LOG(statusInfoMem_ != nullptr, nullptr, "not inited");
500     return (statusInfoMem_->GetBase() + sizeof(BasicBufferInfo));
501 }
502 
GetInitializationInfo()503 OHAudioBufferBase::InitializationInfo OHAudioBufferBase::GetInitializationInfo()
504 {
505     InitializationInfo info = {
506         .bufferHolder = bufferHolder_,
507         .totalSizeInFrame = totalSizeInFrame_,
508         .byteSizePerFrame = byteSizePerFrame_,
509         .dataFd = dataMem_->GetFd(),
510         .infoFd = statusInfoMem_->GetFd()
511     };
512 
513     return info;
514 }
515 
GetSessionId()516 uint32_t OHAudioBufferBase::GetSessionId()
517 {
518     return sessionId_;
519 }
520 
SetSessionId(uint32_t sessionId)521 int32_t OHAudioBufferBase::SetSessionId(uint32_t sessionId)
522 {
523     sessionId_ = sessionId;
524     return SUCCESS;
525 }
526 
GetBufferHolder()527 AudioBufferHolder OHAudioBufferBase::GetBufferHolder()
528 {
529     return bufferHolder_;
530 }
531 
GetSizeParameter(uint32_t & totalSizeInFrame,uint32_t & byteSizePerFrame)532 int32_t OHAudioBufferBase::GetSizeParameter(uint32_t &totalSizeInFrame, uint32_t &byteSizePerFrame)
533 {
534     totalSizeInFrame = totalSizeInFrame_;
535     byteSizePerFrame = byteSizePerFrame_;
536 
537     return SUCCESS;
538 }
539 
GetTotalSizeInFrame()540 uint32_t OHAudioBufferBase::GetTotalSizeInFrame()
541 {
542     return totalSizeInFrame_;
543 }
544 
GetStreamStatus()545 std::atomic<StreamStatus> *OHAudioBufferBase::GetStreamStatus()
546 {
547     if (basicBufferInfo_ == nullptr) {
548         return nullptr;
549     }
550     return &basicBufferInfo_->streamStatus;
551 }
552 
GetUnderrunCount()553 uint32_t OHAudioBufferBase::GetUnderrunCount()
554 {
555     CHECK_AND_RETURN_RET_LOG(basicBufferInfo_ != nullptr, 0,
556         "Get nullptr, buffer is not inited.");
557     return basicBufferInfo_->underrunCount.load();
558 }
559 
SetUnderrunCount(uint32_t count)560 bool OHAudioBufferBase::SetUnderrunCount(uint32_t count)
561 {
562     CHECK_AND_RETURN_RET_LOG(basicBufferInfo_ != nullptr, false,
563         "Get nullptr, buffer is not inited.");
564     basicBufferInfo_->underrunCount.store(count);
565     return true;
566 }
567 
GetHandleInfo(uint64_t & frames,int64_t & nanoTime)568 bool OHAudioBufferBase::GetHandleInfo(uint64_t &frames, int64_t &nanoTime)
569 {
570     CHECK_AND_RETURN_RET_LOG(basicBufferInfo_ != nullptr, false,
571         "Get nullptr, failed to GetHandleInfo.");
572 
573     frames = basicBufferInfo_->handlePos.load();
574     nanoTime = basicBufferInfo_->handleTime.load();
575     return true;
576 }
577 
SetHandleInfo(uint64_t frames,int64_t nanoTime)578 void OHAudioBufferBase::SetHandleInfo(uint64_t frames, int64_t nanoTime)
579 {
580     basicBufferInfo_->handlePos.store(frames);
581     basicBufferInfo_->handleTime.store(nanoTime);
582 }
583 
GetStreamVolume()584 float OHAudioBufferBase::GetStreamVolume()
585 {
586     CHECK_AND_RETURN_RET_LOG(basicBufferInfo_ != nullptr, MAX_FLOAT_VOLUME, "buffer is not inited!");
587     float vol = basicBufferInfo_->streamVolume.load();
588     if (vol < MIN_FLOAT_VOLUME) {
589         AUDIO_WARNING_LOG("vol < 0.0, invalid volume! using 0.0 instead.");
590         return MIN_FLOAT_VOLUME;
591     } else if (vol > MAX_FLOAT_VOLUME) {
592         AUDIO_WARNING_LOG("vol > 0.0, invalid volume! using 1.0 instead.");
593         return MAX_FLOAT_VOLUME;
594     }
595     return vol;
596 }
597 
SetStreamVolume(float streamVolume)598 bool OHAudioBufferBase::SetStreamVolume(float streamVolume)
599 {
600     CHECK_AND_RETURN_RET_LOG(basicBufferInfo_ != nullptr, false, "buffer is not inited!");
601     if (streamVolume < MIN_FLOAT_VOLUME || streamVolume > MAX_FLOAT_VOLUME) {
602         AUDIO_ERR_LOG("invlaid volume:%{public}f", streamVolume);
603         return false;
604     }
605     basicBufferInfo_->streamVolume.store(streamVolume);
606     return true;
607 }
608 
GetMuteFactor()609 float OHAudioBufferBase::GetMuteFactor()
610 {
611     CHECK_AND_RETURN_RET_LOG(basicBufferInfo_ != nullptr, MAX_FLOAT_VOLUME, "buffer is not inited!");
612     float factor = basicBufferInfo_->muteFactor.load();
613     if (factor < MIN_FLOAT_VOLUME) {
614         AUDIO_WARNING_LOG("vol < 0.0, invalid muteFactor! using 0.0 instead.");
615         return MIN_FLOAT_VOLUME;
616     } else if (factor > MAX_FLOAT_VOLUME) {
617         AUDIO_WARNING_LOG("vol > 0.0, invalid muteFactor! using 1.0 instead.");
618         return MAX_FLOAT_VOLUME;
619     }
620     return factor;
621 }
622 
SetMuteFactor(float muteFactor)623 bool OHAudioBufferBase::SetMuteFactor(float muteFactor)
624 {
625     CHECK_AND_RETURN_RET_LOG(basicBufferInfo_ != nullptr, false, "buffer is not inited!");
626     if (muteFactor != MIN_FLOAT_VOLUME && muteFactor != MAX_FLOAT_VOLUME) {
627         AUDIO_ERR_LOG("invlaid factor:%{public}f", muteFactor);
628         return false;
629     }
630     basicBufferInfo_->muteFactor.store(muteFactor);
631     return true;
632 }
633 
GetDuckFactor()634 float OHAudioBufferBase::GetDuckFactor()
635 {
636     CHECK_AND_RETURN_RET_LOG(basicBufferInfo_ != nullptr, MAX_FLOAT_VOLUME, "buffer is not inited!");
637     float factor = basicBufferInfo_->duckFactor.load();
638     if (factor < MIN_FLOAT_VOLUME) {
639         AUDIO_WARNING_LOG("vol < 0.0, invalid duckFactor! using 0.0 instead.");
640         return MIN_FLOAT_VOLUME;
641     } else if (factor > MAX_FLOAT_VOLUME) {
642         AUDIO_WARNING_LOG("vol > 0.0, invalid duckFactor! using 1.0 instead.");
643         return MAX_FLOAT_VOLUME;
644     }
645     return factor;
646 }
647 
SetDuckFactor(float duckFactor)648 bool OHAudioBufferBase::SetDuckFactor(float duckFactor)
649 {
650     CHECK_AND_RETURN_RET_LOG(basicBufferInfo_ != nullptr, false, "buffer is not inited!");
651     if (duckFactor < MIN_FLOAT_VOLUME || duckFactor > MAX_FLOAT_VOLUME) {
652         AUDIO_ERR_LOG("invlaid factor:%{public}f", duckFactor);
653         return false;
654     }
655     basicBufferInfo_->duckFactor.store(duckFactor);
656     return true;
657 }
658 
GetWritableDataFrames()659 int32_t OHAudioBufferBase::GetWritableDataFrames()
660 {
661     int32_t result = -1; // failed
662     uint64_t write = basicBufferInfo_->curWriteFrame.load();
663     uint64_t read = basicBufferInfo_->curReadFrame.load();
664     CHECK_AND_RETURN_RET_LOG(write >= read, result, "invalid write and read position.");
665     uint32_t temp = write - read;
666     CHECK_AND_RETURN_RET_LOG(temp <= INT32_MAX && temp <= totalSizeInFrame_,
667         result, "failed to GetWritableDataFrames.");
668     result = static_cast<int32_t>(totalSizeInFrame_ - temp);
669     return result;
670 }
671 
GetReadableDataFrames()672 int32_t OHAudioBufferBase::GetReadableDataFrames()
673 {
674     int32_t result = -1; // failed
675     uint64_t write = basicBufferInfo_->curWriteFrame.load();
676     uint64_t read = basicBufferInfo_->curReadFrame.load();
677     CHECK_AND_RETURN_RET_LOG(write >= read, result, "invalid write and read position.");
678     uint32_t temp = write - read;
679     CHECK_AND_RETURN_RET_LOG(temp <= INT32_MAX && temp <= totalSizeInFrame_,
680         result, "failed to GetWritableDataFrames.");
681     result = static_cast<int32_t>(temp);
682     return result;
683 }
684 
ResetCurReadWritePos(uint64_t readFrame,uint64_t writeFrame,bool wakeFutex)685 int32_t OHAudioBufferBase::ResetCurReadWritePos(uint64_t readFrame, uint64_t writeFrame, bool wakeFutex)
686 {
687     CHECK_AND_RETURN_RET_LOG(readFrame <= writeFrame && writeFrame - readFrame < totalSizeInFrame_,
688         ERR_INVALID_PARAM, "Invalid read or write position:read%{public}" PRIu64" write%{public}" PRIu64".",
689         readFrame, writeFrame);
690     uint64_t tempBase = (readFrame / totalSizeInFrame_) * totalSizeInFrame_;
691     basicBufferInfo_->basePosInFrame.store(tempBase);
692     basicBufferInfo_->curWriteFrame.store(writeFrame);
693     basicBufferInfo_->curReadFrame.store(readFrame);
694 
695     AUDIO_DEBUG_LOG("Reset position:read%{public}" PRIu64" write%{public}" PRIu64".", readFrame, writeFrame);
696 
697     CHECK_AND_RETURN_RET(wakeFutex, SUCCESS);
698 
699     WakeFutexIfNeed();
700 
701     return SUCCESS;
702 }
703 
GetCurWriteFrame()704 uint64_t OHAudioBufferBase::GetCurWriteFrame()
705 {
706     CHECK_AND_RETURN_RET_LOG(basicBufferInfo_ != nullptr, 0, "basicBufferInfo_ is null");
707     return basicBufferInfo_->curWriteFrame.load();
708 }
709 
GetCurReadFrame()710 uint64_t OHAudioBufferBase::GetCurReadFrame()
711 {
712     CHECK_AND_RETURN_RET_LOG(basicBufferInfo_ != nullptr, 0, "basicBufferInfo_ is null");
713     return basicBufferInfo_->curReadFrame.load();
714 }
715 
GetBasePosInFrame()716 uint64_t OHAudioBufferBase::GetBasePosInFrame()
717 {
718     CHECK_AND_RETURN_RET_LOG(basicBufferInfo_ != nullptr, 0, "basicBufferInfo_ is null");
719     return basicBufferInfo_->basePosInFrame.load();
720 }
721 
SetCurWriteFrame(uint64_t writeFrame,bool wakeFutex)722 int32_t OHAudioBufferBase::SetCurWriteFrame(uint64_t writeFrame, bool wakeFutex)
723 {
724     uint64_t basePos = basicBufferInfo_->basePosInFrame.load();
725     uint64_t oldWritePos = basicBufferInfo_->curWriteFrame.load();
726     if (writeFrame == oldWritePos) {
727         return SUCCESS;
728     }
729     CHECK_AND_RETURN_RET_LOG(writeFrame > oldWritePos, ERR_INVALID_PARAM, "Too small writeFrame:%{public}" PRIu64".",
730         writeFrame);
731 
732     uint64_t deltaToBase = writeFrame - basePos; // writeFrame % spanSizeInFrame_ --> 0
733 
734     // check new pos in range: base ~ base + 2*total
735     CHECK_AND_RETURN_RET_LOG(deltaToBase < (totalSizeInFrame_ + totalSizeInFrame_),
736         ERR_INVALID_PARAM, "Invalid writeFrame %{public}" PRIu64" out of base range.", writeFrame);
737 
738     // check new pos in (read + cache) range: read ~ read + totalSize - 1*spanSize
739     uint64_t curRead = basicBufferInfo_->curReadFrame.load();
740     CHECK_AND_RETURN_RET_LOG(writeFrame >= curRead && writeFrame - curRead <= totalSizeInFrame_,
741         ERR_INVALID_PARAM, "Invalid writeFrame %{public}" PRIu64" out of cache range, curRead %{public}" PRIu64".",
742         writeFrame, curRead);
743 
744     basicBufferInfo_->curWriteFrame.store(writeFrame);
745 
746     CHECK_AND_RETURN_RET(wakeFutex, SUCCESS);
747 
748     WakeFutexIfNeed();
749 
750     return SUCCESS;
751 }
752 
SetCurReadFrame(uint64_t readFrame,bool wakeFutex)753 int32_t OHAudioBufferBase::SetCurReadFrame(uint64_t readFrame, bool wakeFutex)
754 {
755     CHECK_AND_RETURN_RET_LOG(basicBufferInfo_ != nullptr, ERR_INVALID_PARAM, "basicBufferInfo_ is nullptr");
756     uint64_t oldBasePos = basicBufferInfo_->basePosInFrame.load();
757     uint64_t oldReadPos = basicBufferInfo_->curReadFrame.load();
758     if (readFrame == oldReadPos) {
759         return SUCCESS;
760     }
761 
762     // new read position should not be bigger than write position or less than old read position
763     CHECK_AND_RETURN_RET_LOG(readFrame >= oldReadPos && readFrame <= basicBufferInfo_->curWriteFrame.load(),
764         ERR_INVALID_PARAM, "Invalid readFrame %{public}" PRIu64".", readFrame);
765 
766     uint64_t deltaToBase = readFrame - oldBasePos;
767 
768     if (deltaToBase >= totalSizeInFrame_) {
769         basicBufferInfo_->basePosInFrame.store(oldBasePos + totalSizeInFrame_); // move base position
770     }
771 
772     basicBufferInfo_->curReadFrame.store(readFrame);
773 
774     CHECK_AND_RETURN_RET(wakeFutex, SUCCESS);
775 
776     WakeFutexIfNeed();
777 
778     return SUCCESS;
779 }
780 
GetOffsetByFrame(uint64_t posInFrame,size_t & offset)781 int32_t OHAudioBufferBase::GetOffsetByFrame(uint64_t posInFrame, size_t &offset)
782 {
783     uint64_t basePos = basicBufferInfo_->basePosInFrame.load();
784     uint64_t maxDelta = 2 * totalSizeInFrame_; // 0 ~ 2*totalSizeInFrame_
785     CHECK_AND_RETURN_RET_LOG(posInFrame >= basePos && posInFrame - basePos < maxDelta,
786         ERR_INVALID_PARAM, "Invalid position:%{public}" PRIu64".", posInFrame);
787 
788     uint32_t deltaToBase = posInFrame - basePos;
789     if (deltaToBase >= totalSizeInFrame_) {
790         deltaToBase -= totalSizeInFrame_;
791     }
792     CHECK_AND_RETURN_RET_LOG(deltaToBase < UINT32_MAX && deltaToBase < totalSizeInFrame_, ERR_INVALID_PARAM,
793         "invalid deltaToBase, posInFrame %{public}" PRIu64" basePos %{public}" PRIu64".", posInFrame, basePos);
794 
795     offset = deltaToBase * byteSizePerFrame_;
796     return SUCCESS;
797 }
798 
GetOffsetByFrameForWrite(uint64_t writePosInFrame,size_t & offset)799 int32_t OHAudioBufferBase::GetOffsetByFrameForWrite(uint64_t writePosInFrame, size_t &offset)
800 {
801     uint64_t basePos = basicBufferInfo_->basePosInFrame.load();
802     uint64_t readPos = basicBufferInfo_->curReadFrame.load();
803     uint64_t maxWriteDelta = 2 * totalSizeInFrame_; // 0 ~ 2*totalSizeInFrame_
804     CHECK_AND_RETURN_RET_LOG(writePosInFrame >= basePos && writePosInFrame - basePos < maxWriteDelta &&
805         writePosInFrame >= readPos, ERR_INVALID_PARAM, "Invalid write position:%{public}" PRIu64".", writePosInFrame);
806     return GetOffsetByFrame(writePosInFrame, offset);
807 }
808 
GetOffsetByFrameForRead(uint64_t readPosInFrame,size_t & offset)809 int32_t OHAudioBufferBase::GetOffsetByFrameForRead(uint64_t readPosInFrame, size_t &offset)
810 {
811     uint64_t basePos = basicBufferInfo_->basePosInFrame.load();
812     CHECK_AND_RETURN_RET_LOG(readPosInFrame >= basePos && readPosInFrame - basePos < totalSizeInFrame_,
813         ERR_INVALID_PARAM, "Invalid read position:%{public}" PRIu64".", readPosInFrame);
814     return GetOffsetByFrame(readPosInFrame, offset);
815 }
816 
GetBufferByOffset(size_t offset,size_t dataLength,RingBufferWrapper & buffer)817 int32_t OHAudioBufferBase::GetBufferByOffset(size_t offset, size_t dataLength, RingBufferWrapper &buffer)
818 {
819     CHECK_AND_RETURN_RET_LOG(offset < totalSizeInByte_, ERR_INVALID_PARAM, "invalid offset:%{public}zu", offset);
820     CHECK_AND_RETURN_RET_LOG((dataLength <= totalSizeInByte_) && (dataLength > 0), ERR_INVALID_PARAM,
821         "invalid dataLength: %{public}zu", dataLength);
822 
823     size_t bufLengthToDataBaseEnd = (totalSizeInByte_ - offset);
824 
825     RingBufferWrapper bufferWrapper;
826     bufferWrapper.dataLength = dataLength;
827 
828     bufferWrapper.basicBufferDescs[0].buffer = dataBase_ + offset;
829     bufferWrapper.basicBufferDescs[0].bufLength = std::min(bufLengthToDataBaseEnd, dataLength);
830 
831     if (dataLength > bufLengthToDataBaseEnd) {
832         bufferWrapper.basicBufferDescs[1].buffer = dataBase_;
833         bufferWrapper.basicBufferDescs[1].bufLength = dataLength - bufLengthToDataBaseEnd;
834     } else {
835         bufferWrapper.basicBufferDescs[1].buffer = nullptr;
836         bufferWrapper.basicBufferDescs[1].bufLength = 0;
837     }
838 
839     buffer = bufferWrapper;
840 
841     return SUCCESS;
842 }
843 
TryGetContinuousBufferByOffset(size_t offset,size_t dataLength,BufferDesc & bufferDesc)844 int32_t OHAudioBufferBase::TryGetContinuousBufferByOffset(size_t offset, size_t dataLength, BufferDesc &bufferDesc)
845 {
846     RingBufferWrapper buffer;
847     int32_t ret = GetBufferByOffset(offset, dataLength, buffer);
848     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "failed!");
849 
850     size_t firstBuffLenth = buffer.basicBufferDescs[0].bufLength;
851     CHECK_AND_RETURN_RET_LOG(dataLength == firstBuffLenth, ERR_INVALID_PARAM,
852         "err dataLength: %{public}zu firstBuffLenth: %{public}zu",
853         dataLength, firstBuffLenth);
854 
855     bufferDesc.buffer = buffer.basicBufferDescs[0].buffer;
856     bufferDesc.bufLength = dataLength;
857     bufferDesc.dataLength = dataLength;
858     return SUCCESS;
859 }
860 
861 // [beginPosInFrame, endPosInFrame)
GetBufferByFrame(uint64_t beginPosInFrame,uint64_t sizeInFrame,RingBufferWrapper & buffer)862 int32_t OHAudioBufferBase::GetBufferByFrame(uint64_t beginPosInFrame, uint64_t sizeInFrame, RingBufferWrapper &buffer)
863 {
864     CHECK_AND_RETURN_RET_LOG((sizeInFrame > 0) && (sizeInFrame <= totalSizeInFrame_),
865         ERR_INVALID_PARAM, "invalid param begin: %{public}" PRIu64 "sizeInFrame: %{public}" PRIu64 "",
866         beginPosInFrame, sizeInFrame);
867 
868     size_t offset;
869     int32_t ret = GetOffsetByFrame(beginPosInFrame, offset);
870     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "getOffset err: %{public}d", ret);
871 
872     size_t dataLength = sizeInFrame * byteSizePerFrame_;
873 
874     return GetBufferByOffset(offset, dataLength, buffer);
875 }
876 
GetAllWritableBufferFromPosFrame(uint64_t writePosInFrame,RingBufferWrapper & buffer)877 int32_t OHAudioBufferBase::GetAllWritableBufferFromPosFrame(uint64_t writePosInFrame, RingBufferWrapper &buffer)
878 {
879     uint64_t basePos = basicBufferInfo_->basePosInFrame.load();
880     uint64_t readPos = basicBufferInfo_->curReadFrame.load();
881     uint64_t maxWriteDelta = 2 * totalSizeInFrame_; // 0 ~ 2*totalSizeInFrame_
882     CHECK_AND_RETURN_RET_LOG(writePosInFrame >= basePos && writePosInFrame - basePos < maxWriteDelta &&
883         writePosInFrame >= readPos && (readPos + totalSizeInFrame_ >= writePosInFrame),
884         ERR_INVALID_PARAM, "Invalid write position:%{public}" PRIu64".", writePosInFrame);
885 
886     uint64_t sizeInFrame = readPos + totalSizeInFrame_ - writePosInFrame;
887     if (sizeInFrame == 0) {
888         buffer.Reset();
889         return SUCCESS;
890     }
891 
892     return GetBufferByFrame(writePosInFrame, sizeInFrame, buffer);
893 }
894 
GetAllWritableBuffer(RingBufferWrapper & buffer)895 int32_t OHAudioBufferBase::GetAllWritableBuffer(RingBufferWrapper &buffer)
896 {
897     uint64_t writePosInFrame = GetCurWriteFrame();
898     return GetAllWritableBufferFromPosFrame(writePosInFrame, buffer);
899 }
900 
GetAllReadableBufferFromPosFrame(uint64_t readPosInFrame,RingBufferWrapper & buffer)901 int32_t OHAudioBufferBase::GetAllReadableBufferFromPosFrame(uint64_t readPosInFrame, RingBufferWrapper &buffer)
902 {
903     uint64_t basePos = basicBufferInfo_->basePosInFrame.load();
904     uint64_t writePos = basicBufferInfo_->curWriteFrame.load();
905 
906     CHECK_AND_RETURN_RET_LOG((readPosInFrame >= basePos) && (readPosInFrame - basePos < totalSizeInFrame_) &&
907         (readPosInFrame <= writePos),
908         ERR_INVALID_PARAM, "Invalid read position:%{public}" PRIu64".", readPosInFrame);
909 
910     uint64_t sizeInFrame = writePos - readPosInFrame;
911     if (sizeInFrame == 0) {
912         buffer.Reset();
913         return SUCCESS;
914     }
915 
916     return GetBufferByFrame(readPosInFrame, sizeInFrame, buffer);
917 }
918 
GetAllReadableBuffer(RingBufferWrapper & buffer)919 int32_t OHAudioBufferBase::GetAllReadableBuffer(RingBufferWrapper &buffer)
920 {
921     uint64_t readPosInFrame = GetCurReadFrame();
922     return GetAllReadableBufferFromPosFrame(readPosInFrame, buffer);
923 }
924 
GetLastWrittenTime()925 int64_t OHAudioBufferBase::GetLastWrittenTime()
926 {
927     return lastWrittenTime_;
928 }
929 
SetLastWrittenTime(int64_t time)930 void OHAudioBufferBase::SetLastWrittenTime(int64_t time)
931 {
932     lastWrittenTime_ = time;
933 }
934 
GetSyncWriteFrame()935 uint32_t OHAudioBufferBase::GetSyncWriteFrame()
936 {
937     if (bufferHolder_ != AUDIO_SERVER_ONLY_WITH_SYNC || syncWriteFrame_ == nullptr) {
938         AUDIO_WARNING_LOG("sync info not support with holder: %{public}d", bufferHolder_);
939         return 0;
940     }
941     return *syncWriteFrame_;
942 }
943 
SetSyncWriteFrame(uint32_t writeFrame)944 bool OHAudioBufferBase::SetSyncWriteFrame(uint32_t writeFrame)
945 {
946     if (bufferHolder_ != AUDIO_SERVER_ONLY_WITH_SYNC || syncWriteFrame_ == nullptr) {
947         AUDIO_WARNING_LOG("sync info not support with holder: %{public}d", bufferHolder_);
948         return false;
949     }
950     *syncWriteFrame_ = writeFrame;
951     return true;
952 }
953 
GetSyncReadFrame()954 uint32_t OHAudioBufferBase::GetSyncReadFrame()
955 {
956     if (bufferHolder_ != AUDIO_SERVER_ONLY_WITH_SYNC || syncReadFrame_ == nullptr) {
957         AUDIO_WARNING_LOG("sync info not support with holder: %{public}d", bufferHolder_);
958         return 0;
959     }
960     return *syncReadFrame_;
961 }
962 
SetSyncReadFrame(uint32_t readFrame)963 bool OHAudioBufferBase::SetSyncReadFrame(uint32_t readFrame)
964 {
965     if (bufferHolder_ != AUDIO_SERVER_ONLY_WITH_SYNC || syncReadFrame_ == nullptr) {
966         AUDIO_WARNING_LOG("sync info not support with holder: %{public}d", bufferHolder_);
967         return false;
968     }
969     *syncReadFrame_ = readFrame;
970     return true;
971 }
972 
GetFutex()973 std::atomic<uint32_t> *OHAudioBufferBase::GetFutex()
974 {
975     if (basicBufferInfo_ == nullptr) {
976         AUDIO_WARNING_LOG("basicBufferInfo_ is nullptr");
977         return nullptr;
978     }
979     return &basicBufferInfo_->futexObj;
980 }
981 
GetDataBase()982 uint8_t *OHAudioBufferBase::GetDataBase()
983 {
984     return dataBase_;
985 }
986 
GetDataSize()987 size_t OHAudioBufferBase::GetDataSize()
988 {
989     return totalSizeInByte_;
990 }
991 
GetRestoreInfo(RestoreInfo & restoreInfo)992 void OHAudioBufferBase::GetRestoreInfo(RestoreInfo &restoreInfo)
993 {
994     CHECK_AND_RETURN_LOG(basicBufferInfo_ != nullptr, "basicBufferInfo_ is nullptr");
995     restoreInfo = basicBufferInfo_->restoreInfo;
996 }
997 
SetRestoreInfo(RestoreInfo restoreInfo)998 void OHAudioBufferBase::SetRestoreInfo(RestoreInfo restoreInfo)
999 {
1000     CHECK_AND_RETURN_LOG(basicBufferInfo_ != nullptr, "basicBufferInfo_ is nullptr");
1001     basicBufferInfo_->restoreInfo = restoreInfo;
1002 }
1003 
GetTimeStampInfo(uint64_t & position,uint64_t & timeStamp)1004 void OHAudioBufferBase::GetTimeStampInfo(uint64_t &position, uint64_t &timeStamp)
1005 {
1006     CHECK_AND_RETURN_LOG(basicBufferInfo_ != nullptr, "basicBufferInfo_ is nullptr");
1007     position = basicBufferInfo_->position.load();
1008     timeStamp = basicBufferInfo_->timeStamp.load();
1009 }
1010 
SetTimeStampInfo(uint64_t position,uint64_t timeStamp)1011 void OHAudioBufferBase::SetTimeStampInfo(uint64_t position, uint64_t timeStamp)
1012 {
1013     CHECK_AND_RETURN_LOG(basicBufferInfo_ != nullptr, "basicBufferInfo_ is nullptr");
1014     basicBufferInfo_->position.store(position);
1015     basicBufferInfo_->timeStamp.store(timeStamp);
1016 }
1017 
GetRestoreStatus()1018 RestoreStatus OHAudioBufferBase::GetRestoreStatus()
1019 {
1020     CHECK_AND_RETURN_RET_LOG(basicBufferInfo_ != nullptr, RESTORE_ERROR, "basicBufferInfo_ is nullptr");
1021     return basicBufferInfo_->restoreStatus.load();
1022 }
1023 
1024 // Compare and swap restore status. If current restore status is NEED_RESTORE, turn it into RESTORING
1025 // to avoid multiple restore.
CheckRestoreStatus()1026 RestoreStatus OHAudioBufferBase::CheckRestoreStatus()
1027 {
1028     CHECK_AND_RETURN_RET_LOG(basicBufferInfo_ != nullptr, RESTORE_ERROR, "basicBufferInfo_ is nullptr");
1029     RestoreStatus expectedStatus = NEED_RESTORE;
1030     basicBufferInfo_->restoreStatus.compare_exchange_strong(expectedStatus, RESTORING);
1031     return expectedStatus;
1032 }
1033 
1034 // Allow client to set restore status to NO_NEED_FOR_RESTORE if unnecessary restore happens. Restore status
1035 // can be set to NEED_RESTORE only when it is currently NO_NEED_FOR_RESTORE(and vice versa).
SetRestoreStatus(RestoreStatus restoreStatus)1036 RestoreStatus OHAudioBufferBase::SetRestoreStatus(RestoreStatus restoreStatus)
1037 {
1038     CHECK_AND_RETURN_RET_LOG(basicBufferInfo_ != nullptr, RESTORE_ERROR, "basicBufferInfo_ is nullptr");
1039     RestoreStatus expectedStatus = RESTORE_ERROR;
1040     if (restoreStatus == NEED_RESTORE) {
1041         expectedStatus = NO_NEED_FOR_RESTORE;
1042         basicBufferInfo_->restoreStatus.compare_exchange_strong(expectedStatus, NEED_RESTORE);
1043     } else if (restoreStatus == NO_NEED_FOR_RESTORE) {
1044         expectedStatus = RESTORING;
1045         basicBufferInfo_->restoreStatus.compare_exchange_strong(expectedStatus, NO_NEED_FOR_RESTORE);
1046     }
1047     return expectedStatus;
1048 }
1049 
SetStopFlag(bool isNeedStop)1050 void OHAudioBufferBase::SetStopFlag(bool isNeedStop)
1051 {
1052     CHECK_AND_RETURN_LOG(basicBufferInfo_ != nullptr, "basicBufferInfo_ is nullptr");
1053     basicBufferInfo_->isNeedStop.store(isNeedStop);
1054 }
1055 
GetStopFlag() const1056 bool OHAudioBufferBase::GetStopFlag() const
1057 {
1058     CHECK_AND_RETURN_RET_LOG(basicBufferInfo_ != nullptr, false, "basicBufferInfo_ is nullptr");
1059     bool isNeedStop = basicBufferInfo_->isNeedStop.exchange(false);
1060     return isNeedStop;
1061 }
1062 
WaitFor(int64_t timeoutInNs,const OnIndexChange & pred)1063 FutexCode OHAudioBufferBase::WaitFor(int64_t timeoutInNs, const OnIndexChange &pred)
1064 {
1065     return FutexTool::FutexWait(GetFutex(), timeoutInNs, [&pred] () {
1066         return pred();
1067     });
1068 }
1069 
InitBasicBufferInfo()1070 void OHAudioBufferBase::InitBasicBufferInfo()
1071 {
1072     // As basicBufferInfo_ is created from memory, we need to set the value with 0.
1073     basicBufferInfo_->basePosInFrame.store(0);
1074     basicBufferInfo_->curReadFrame.store(0);
1075     basicBufferInfo_->curWriteFrame.store(0);
1076 
1077     basicBufferInfo_->underrunCount.store(0);
1078 
1079     basicBufferInfo_->position.store(0);
1080     basicBufferInfo_->timeStamp.store(0);
1081 
1082     basicBufferInfo_->streamVolume.store(MAX_FLOAT_VOLUME);
1083     basicBufferInfo_->duckFactor.store(MAX_FLOAT_VOLUME);
1084     basicBufferInfo_->muteFactor.store(MAX_FLOAT_VOLUME);
1085 }
1086 
WakeFutexIfNeed(uint32_t wakeVal)1087 void OHAudioBufferBase::WakeFutexIfNeed(uint32_t wakeVal)
1088 {
1089     if (basicBufferInfo_) {
1090         FutexTool::FutexWake(&(basicBufferInfo_->futexObj), wakeVal);
1091     }
1092 }
1093 
WakeFutex(uint32_t wakeVal)1094 void OHAudioBufferBase::WakeFutex(uint32_t wakeVal)
1095 {
1096     WakeFutexIfNeed(wakeVal);
1097 }
1098 } // namespace AudioStandard
1099 } // namespace OHOS
1100