• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 "OHAudioBuffer"
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 
31 namespace OHOS {
32 namespace AudioStandard {
33 namespace {
34     static const int INVALID_FD = -1;
35     static const size_t MAX_MMAP_BUFFER_SIZE = 10 * 1024 * 1024; // 10M
36     static const std::string STATUS_INFO_BUFFER = "status_info_buffer";
37 }
38 class AudioSharedMemoryImpl : public AudioSharedMemory {
39 public:
40     uint8_t *GetBase() override;
41     size_t GetSize() override;
42     int GetFd() override;
43     std::string GetName() override;
44 
45     AudioSharedMemoryImpl(size_t size, const std::string &name);
46 
47     AudioSharedMemoryImpl(int fd, size_t size, const std::string &name);
48 
49     ~AudioSharedMemoryImpl();
50 
51     int32_t Init();
52 
53 private:
54     void Close();
55 
56     uint8_t *base_;
57     int fd_;
58     size_t size_;
59     std::string name_;
60 };
61 
AudioSharedMemoryImpl(size_t size,const std::string & name)62 AudioSharedMemoryImpl::AudioSharedMemoryImpl(size_t size, const std::string &name)
63     : base_(nullptr), fd_(INVALID_FD), size_(size), name_(name)
64 {
65     AUDIO_DEBUG_LOG("AudioSharedMemory ctor with size: %{public}zu name: %{public}s", size_, name_.c_str());
66 }
67 
AudioSharedMemoryImpl(int fd,size_t size,const std::string & name)68 AudioSharedMemoryImpl::AudioSharedMemoryImpl(int fd, size_t size, const std::string &name)
69     : base_(nullptr), fd_(dup(fd)), size_(size), name_(name)
70 {
71     AUDIO_DEBUG_LOG("AudioSharedMemory ctor with fd %{public}d size %{public}zu name %{public}s", fd_, size_,
72         name_.c_str());
73 }
74 
~AudioSharedMemoryImpl()75 AudioSharedMemoryImpl::~AudioSharedMemoryImpl()
76 {
77     AUDIO_DEBUG_LOG(" %{public}s enter ~AudioSharedMemoryImpl()", name_.c_str());
78     Close();
79 }
80 
Init()81 int32_t AudioSharedMemoryImpl::Init()
82 {
83     CHECK_AND_RETURN_RET_LOG((size_ > 0 && size_ < MAX_MMAP_BUFFER_SIZE), ERR_INVALID_PARAM,
84         "Init falied: size out of range: %{public}zu", size_);
85     bool isFromRemote = false;
86     if (fd_ > 0) {
87         isFromRemote = true;
88         int size = AshmemGetSize(fd_); // hdi fd may not support
89         if (size < 0 || static_cast<size_t>(size) != size_) {
90             AUDIO_WARNING_LOG("AshmemGetSize faied, get %{public}d", size);
91         }
92     } else {
93         fd_ = AshmemCreate(name_.c_str(), size_);
94         CHECK_AND_RETURN_RET_LOG((fd_ > 0), ERR_OPERATION_FAILED, "Init falied: fd %{public}d", fd_);
95     }
96 
97     void *addr = mmap(nullptr, size_, PROT_READ | PROT_WRITE, MAP_SHARED, fd_, 0);
98     CHECK_AND_RETURN_RET_LOG(addr != MAP_FAILED, ERR_OPERATION_FAILED, "Init falied: fd %{public}d size %{public}zu",
99         fd_, size_);
100     base_ = static_cast<uint8_t *>(addr);
101     AUDIO_DEBUG_LOG("Init %{public}s <%{public}s> done.", (isFromRemote ? "remote" : "local"),
102         name_.c_str());
103     return SUCCESS;
104 }
105 
Close()106 void AudioSharedMemoryImpl::Close()
107 {
108     if (base_ != nullptr) {
109         (void)munmap(base_, size_);
110         base_ = nullptr;
111         size_ = 0;
112         AUDIO_DEBUG_LOG("%{public}s munmap done", name_.c_str());
113     }
114 
115     if (fd_ > 0) {
116         (void)close(fd_);
117         fd_ = INVALID_FD;
118         AUDIO_DEBUG_LOG("%{public}s close fd done", name_.c_str());
119     }
120 }
121 
GetBase()122 uint8_t *AudioSharedMemoryImpl::GetBase()
123 {
124     return base_;
125 }
126 
GetSize()127 size_t AudioSharedMemoryImpl::GetSize()
128 {
129     return size_;
130 }
131 
GetName()132 std::string AudioSharedMemoryImpl::GetName()
133 {
134     return name_;
135 }
136 
GetFd()137 int AudioSharedMemoryImpl::GetFd()
138 {
139     return fd_;
140 }
141 
CreateFormLocal(size_t size,const std::string & name)142 std::shared_ptr<AudioSharedMemory> AudioSharedMemory::CreateFormLocal(size_t size, const std::string &name)
143 {
144     std::shared_ptr<AudioSharedMemoryImpl> sharedMemory = std::make_shared<AudioSharedMemoryImpl>(size, name);
145     CHECK_AND_RETURN_RET_LOG(sharedMemory->Init() == SUCCESS,
146         nullptr, "CreateFormLocal failed");
147     return sharedMemory;
148 }
149 
CreateFromRemote(int fd,size_t size,const std::string & name)150 std::shared_ptr<AudioSharedMemory> AudioSharedMemory::CreateFromRemote(int fd, size_t size, const std::string &name)
151 {
152     int minfd = 2; // ignore stdout, stdin and stderr.
153     CHECK_AND_RETURN_RET_LOG(fd > minfd, nullptr, "CreateFromRemote failed: invalid fd: %{public}d", fd);
154     std::shared_ptr<AudioSharedMemoryImpl> sharedMemory = std::make_shared<AudioSharedMemoryImpl>(fd, size, name);
155     if (sharedMemory->Init() != SUCCESS) {
156         AUDIO_ERR_LOG("CreateFromRemote failed");
157         return nullptr;
158     }
159     return sharedMemory;
160 }
161 
WriteToParcel(const std::shared_ptr<AudioSharedMemory> & memory,MessageParcel & parcel)162 int32_t AudioSharedMemory::WriteToParcel(const std::shared_ptr<AudioSharedMemory> &memory, MessageParcel &parcel)
163 {
164     std::shared_ptr<AudioSharedMemoryImpl> memoryImpl = std::static_pointer_cast<AudioSharedMemoryImpl>(memory);
165     CHECK_AND_RETURN_RET_LOG(memoryImpl != nullptr, ERR_OPERATION_FAILED, "invalid pointer.");
166 
167     int32_t fd = memoryImpl->GetFd();
168 
169     size_t size = memoryImpl->GetSize();
170     CHECK_AND_RETURN_RET_LOG((size > 0 && size < MAX_MMAP_BUFFER_SIZE), ERR_INVALID_PARAM,
171         "invalid size: %{public}zu", size);
172     uint64_t sizeTmp = static_cast<uint64_t>(size);
173 
174     std::string name = memoryImpl->GetName();
175 
176     parcel.WriteFileDescriptor(fd);
177     parcel.WriteUint64(sizeTmp);
178     parcel.WriteString(name);
179 
180     return SUCCESS;
181 }
182 
ReadFromParcel(MessageParcel & parcel)183 std::shared_ptr<AudioSharedMemory> AudioSharedMemory::ReadFromParcel(MessageParcel &parcel)
184 {
185     int fd = parcel.ReadFileDescriptor();
186 
187     uint64_t sizeTmp = parcel.ReadUint64();
188     CHECK_AND_RETURN_RET_LOG((sizeTmp > 0 && sizeTmp < MAX_MMAP_BUFFER_SIZE), nullptr, "failed with invalid size");
189     size_t size = static_cast<size_t>(sizeTmp);
190 
191     std::string name = parcel.ReadString();
192 
193     std::shared_ptr<AudioSharedMemory> memory = AudioSharedMemory::CreateFromRemote(fd, size, name);
194     if (memory == nullptr || memory->GetBase() == nullptr) {
195         AUDIO_ERR_LOG("ReadFromParcel failed");
196         memory = nullptr;
197     }
198     close(fd);
199     return memory;
200 }
201 
202 // OHAudioBuffer
OHAudioBuffer(AudioBufferHolder bufferHolder,uint32_t totalSizeInFrame,uint32_t spanSizeInFrame,uint32_t byteSizePerFrame)203 OHAudioBuffer::OHAudioBuffer(AudioBufferHolder bufferHolder, uint32_t totalSizeInFrame, uint32_t spanSizeInFrame,
204     uint32_t byteSizePerFrame) : bufferHolder_(bufferHolder), totalSizeInFrame_(totalSizeInFrame),
205     spanSizeInFrame_(spanSizeInFrame), byteSizePerFrame_(byteSizePerFrame), audioMode_(AUDIO_MODE_PLAYBACK),
206     basicBufferInfo_(nullptr), spanInfoList_(nullptr)
207 {
208     AUDIO_DEBUG_LOG("ctor with holder:%{public}d mode:%{public}d", bufferHolder_, audioMode_);
209 }
210 
~OHAudioBuffer()211 OHAudioBuffer::~OHAudioBuffer()
212 {
213     AUDIO_DEBUG_LOG("enter ~OHAudioBuffer()");
214     basicBufferInfo_ = nullptr;
215     spanInfoList_ = nullptr;
216     spanConut_ = 0;
217 }
218 
SizeCheck()219 int32_t OHAudioBuffer::SizeCheck()
220 {
221     if (totalSizeInFrame_ < spanSizeInFrame_ || totalSizeInFrame_ % spanSizeInFrame_ != 0 ||
222         totalSizeInFrame_ > UINT_MAX / byteSizePerFrame_) {
223         AUDIO_ERR_LOG("failed: invalid size.");
224         return ERR_INVALID_PARAM;
225     }
226     totalSizeInByte_ = totalSizeInFrame_ * byteSizePerFrame_;
227     // data buffer size check
228     CHECK_AND_RETURN_RET_LOG((totalSizeInByte_ < MAX_MMAP_BUFFER_SIZE), ERR_INVALID_PARAM, "too large totalSizeInByte "
229         "%{public}zu", totalSizeInByte_);
230 
231     spanSizeInByte_ = spanSizeInFrame_ * byteSizePerFrame_;
232     spanConut_ = totalSizeInFrame_ / spanSizeInFrame_;
233 
234     return SUCCESS;
235 }
236 
Init(int dataFd,int infoFd)237 int32_t OHAudioBuffer::Init(int dataFd, int infoFd)
238 {
239     AUDIO_DEBUG_LOG("Init with dataFd %{public}d, infoFd %{public}d, bufferSize %{public}d, spanSize %{public}d,"
240         " byteSizePerFrame %{public}d", dataFd, infoFd, totalSizeInFrame_, spanSizeInFrame_, byteSizePerFrame_);
241 
242     int32_t ret = SizeCheck();
243     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_INVALID_PARAM, "failed: invalid size.");
244 
245     // init for statusInfoBuffer
246     size_t statusInfoSize = sizeof(BasicBufferInfo) + spanConut_ * sizeof(SpanInfo);
247     if (infoFd != INVALID_FD && (bufferHolder_ == AUDIO_CLIENT || bufferHolder_ == AUDIO_SERVER_INDEPENDENT)) {
248         statusInfoMem_ = AudioSharedMemory::CreateFromRemote(infoFd, statusInfoSize, STATUS_INFO_BUFFER);
249     } else {
250         statusInfoMem_ = AudioSharedMemory::CreateFormLocal(statusInfoSize, STATUS_INFO_BUFFER);
251     }
252     CHECK_AND_RETURN_RET_LOG(statusInfoMem_ != nullptr, ERR_OPERATION_FAILED, "BasicBufferInfo mmap failed.");
253 
254     // init for dataBuffer
255     if (dataFd == INVALID_FD && bufferHolder_ == AUDIO_SERVER_SHARED) {
256         dataMem_ = AudioSharedMemory::CreateFormLocal(totalSizeInByte_, "server_client_buffer");
257     } else {
258         std::string memoryDesc = (bufferHolder_ == AUDIO_SERVER_ONLY ? "server_hdi_buffer" : "server_client_buffer");
259         dataMem_ = AudioSharedMemory::CreateFromRemote(dataFd, totalSizeInByte_, memoryDesc);
260     }
261     CHECK_AND_RETURN_RET_LOG(dataMem_ != nullptr, ERR_OPERATION_FAILED, "dataMem_ mmap failed.");
262 
263     dataBase_ = dataMem_->GetBase();
264 
265     basicBufferInfo_ = reinterpret_cast<BasicBufferInfo *>(statusInfoMem_->GetBase());
266     spanInfoList_ = reinterpret_cast<SpanInfo *>(statusInfoMem_->GetBase() + sizeof(BasicBufferInfo));
267 
268     // As basicBufferInfo_ is created from memory, we need to set the value with 0.
269     basicBufferInfo_->basePosInFrame.store(0);
270     basicBufferInfo_->curReadFrame.store(0);
271     basicBufferInfo_->curWriteFrame.store(0);
272 
273     basicBufferInfo_->underrunCount.store(0);
274 
275     basicBufferInfo_->streamVolume.store(MAX_FLOAT_VOLUME);
276     basicBufferInfo_->duckFactor.store(MAX_FLOAT_VOLUME);
277 
278     if (bufferHolder_ == AUDIO_SERVER_SHARED || bufferHolder_ == AUDIO_SERVER_ONLY) {
279         basicBufferInfo_->handlePos.store(0);
280         basicBufferInfo_->handleTime.store(0);
281         basicBufferInfo_->totalSizeInFrame = totalSizeInFrame_;
282         basicBufferInfo_->spanSizeInFrame = spanSizeInFrame_;
283         basicBufferInfo_->byteSizePerFrame = byteSizePerFrame_;
284         basicBufferInfo_->streamStatus.store(STREAM_INVALID);
285 
286         for (uint32_t i = 0; i < spanConut_; i++) {
287             spanInfoList_[i].spanStatus.store(SPAN_INVALID);
288         }
289     }
290 
291     AUDIO_DEBUG_LOG("Init done.");
292     return SUCCESS;
293 }
294 
CreateFromLocal(uint32_t totalSizeInFrame,uint32_t spanSizeInFrame,uint32_t byteSizePerFrame)295 std::shared_ptr<OHAudioBuffer> OHAudioBuffer::CreateFromLocal(uint32_t totalSizeInFrame, uint32_t spanSizeInFrame,
296     uint32_t byteSizePerFrame)
297 {
298     AUDIO_DEBUG_LOG("totalSizeInFrame %{public}d, spanSizeInFrame %{public}d, byteSizePerFrame"
299         " %{public}d", totalSizeInFrame, spanSizeInFrame, byteSizePerFrame);
300 
301     AudioBufferHolder bufferHolder = AudioBufferHolder::AUDIO_SERVER_SHARED;
302     std::shared_ptr<OHAudioBuffer> buffer = std::make_shared<OHAudioBuffer>(bufferHolder, totalSizeInFrame,
303         spanSizeInFrame, byteSizePerFrame);
304     CHECK_AND_RETURN_RET_LOG(buffer->Init(INVALID_FD, INVALID_FD) == SUCCESS,
305         nullptr, "failed to init.");
306     return buffer;
307 }
308 
CreateFromRemote(uint32_t totalSizeInFrame,uint32_t spanSizeInFrame,uint32_t byteSizePerFrame,AudioBufferHolder bufferHolder,int dataFd,int infoFd)309 std::shared_ptr<OHAudioBuffer> OHAudioBuffer::CreateFromRemote(uint32_t totalSizeInFrame, uint32_t spanSizeInFrame,
310     uint32_t byteSizePerFrame, AudioBufferHolder bufferHolder, int dataFd, int infoFd)
311 {
312     AUDIO_DEBUG_LOG("dataFd %{public}d, infoFd %{public}d", dataFd, infoFd);
313 
314     int minfd = 2; // ignore stdout, stdin and stderr.
315     CHECK_AND_RETURN_RET_LOG(dataFd > minfd, nullptr, "invalid dataFd: %{public}d", dataFd);
316 
317     if (infoFd != INVALID_FD) {
318         CHECK_AND_RETURN_RET_LOG(infoFd > minfd, nullptr, "invalid infoFd: %{public}d", infoFd);
319     }
320     std::shared_ptr<OHAudioBuffer> buffer = std::make_shared<OHAudioBuffer>(bufferHolder, totalSizeInFrame,
321         spanSizeInFrame, byteSizePerFrame);
322     if (buffer->Init(dataFd, infoFd) != SUCCESS) {
323         AUDIO_ERR_LOG("failed to init.");
324         return nullptr;
325     }
326     return buffer;
327 }
328 
WriteToParcel(const std::shared_ptr<OHAudioBuffer> & buffer,MessageParcel & parcel)329 int32_t OHAudioBuffer::WriteToParcel(const std::shared_ptr<OHAudioBuffer> &buffer, MessageParcel &parcel)
330 {
331     AUDIO_DEBUG_LOG("WriteToParcel start.");
332     AudioBufferHolder bufferHolder = buffer->GetBufferHolder();
333     CHECK_AND_RETURN_RET_LOG(bufferHolder == AudioBufferHolder::AUDIO_SERVER_SHARED ||
334         bufferHolder == AudioBufferHolder::AUDIO_SERVER_INDEPENDENT,
335         ERROR_INVALID_PARAM, "buffer holder error:%{public}d", bufferHolder);
336 
337     parcel.WriteUint32(bufferHolder);
338     parcel.WriteUint32(buffer->totalSizeInFrame_);
339     parcel.WriteUint32(buffer->spanSizeInFrame_);
340     parcel.WriteUint32(buffer->byteSizePerFrame_);
341 
342     parcel.WriteFileDescriptor(buffer->dataMem_->GetFd());
343     parcel.WriteFileDescriptor(buffer->statusInfoMem_->GetFd());
344 
345     AUDIO_DEBUG_LOG("WriteToParcel done.");
346     return SUCCESS;
347 }
348 
ReadFromParcel(MessageParcel & parcel)349 std::shared_ptr<OHAudioBuffer> OHAudioBuffer::ReadFromParcel(MessageParcel &parcel)
350 {
351     AUDIO_DEBUG_LOG("ReadFromParcel start.");
352     uint32_t holder = parcel.ReadUint32();
353     AudioBufferHolder bufferHolder = static_cast<AudioBufferHolder>(holder);
354     if (bufferHolder != AudioBufferHolder::AUDIO_SERVER_SHARED &&
355         bufferHolder != AudioBufferHolder::AUDIO_SERVER_INDEPENDENT) {
356         AUDIO_ERR_LOG("ReadFromParcel buffer holder error:%{public}d", bufferHolder);
357         return nullptr;
358     }
359     bufferHolder = bufferHolder == AudioBufferHolder::AUDIO_SERVER_SHARED ?
360          AudioBufferHolder::AUDIO_CLIENT : bufferHolder;
361     uint32_t totalSizeInFrame = parcel.ReadUint32();
362     uint32_t spanSizeInFrame = parcel.ReadUint32();
363     uint32_t byteSizePerFrame = parcel.ReadUint32();
364 
365     int dataFd = parcel.ReadFileDescriptor();
366     int infoFd = parcel.ReadFileDescriptor();
367 
368     std::shared_ptr<OHAudioBuffer> buffer = OHAudioBuffer::CreateFromRemote(totalSizeInFrame, spanSizeInFrame,
369         byteSizePerFrame, bufferHolder, dataFd, infoFd);
370     if (buffer == nullptr) {
371         AUDIO_ERR_LOG("ReadFromParcel failed.");
372     } else if (totalSizeInFrame != buffer->basicBufferInfo_->totalSizeInFrame ||
373         spanSizeInFrame != buffer->basicBufferInfo_->spanSizeInFrame ||
374         byteSizePerFrame != buffer->basicBufferInfo_->byteSizePerFrame) {
375         AUDIO_WARNING_LOG("data in shared memory diff.");
376     } else {
377         AUDIO_DEBUG_LOG("Read some data done.");
378     }
379     close(dataFd);
380     close(infoFd);
381     AUDIO_DEBUG_LOG("ReadFromParcel done.");
382     return buffer;
383 }
384 
GetBufferHolder()385 AudioBufferHolder OHAudioBuffer::GetBufferHolder()
386 {
387     return bufferHolder_;
388 }
389 
GetSizeParameter(uint32_t & totalSizeInFrame,uint32_t & spanSizeInFrame,uint32_t & byteSizePerFrame)390 int32_t OHAudioBuffer::GetSizeParameter(uint32_t &totalSizeInFrame, uint32_t &spanSizeInFrame,
391     uint32_t &byteSizePerFrame)
392 {
393     totalSizeInFrame = totalSizeInFrame_;
394     spanSizeInFrame = spanSizeInFrame_;
395     byteSizePerFrame = byteSizePerFrame_;
396 
397     return SUCCESS;
398 }
399 
GetStreamStatus()400 std::atomic<StreamStatus> *OHAudioBuffer::GetStreamStatus()
401 {
402     if (basicBufferInfo_ == nullptr) {
403         return nullptr;
404     }
405     return &basicBufferInfo_->streamStatus;
406 }
407 
408 
GetStreamVolume()409 float OHAudioBuffer::GetStreamVolume()
410 {
411     CHECK_AND_RETURN_RET_LOG(basicBufferInfo_ != nullptr, MAX_FLOAT_VOLUME, "buffer is not inited!");
412     float vol = basicBufferInfo_->streamVolume.load();
413     if (vol < MIN_FLOAT_VOLUME) {
414         AUDIO_WARNING_LOG("vol < 0.0, invalid volume! using 0.0 instead.");
415         return MIN_FLOAT_VOLUME;
416     } else if (vol > MAX_FLOAT_VOLUME) {
417         AUDIO_WARNING_LOG("vol > 0.0, invalid volume! using 1.0 instead.");
418         return MAX_FLOAT_VOLUME;
419     }
420     return vol;
421 }
422 
SetStreamVolume(float streamVolume)423 bool OHAudioBuffer::SetStreamVolume(float streamVolume)
424 {
425     CHECK_AND_RETURN_RET_LOG(basicBufferInfo_ != nullptr, false, "buffer is not inited!");
426     if (streamVolume < MIN_FLOAT_VOLUME || streamVolume > MAX_FLOAT_VOLUME) {
427         AUDIO_ERR_LOG("invlaid volume:%{public}f", streamVolume);
428         return false;
429     }
430     basicBufferInfo_->streamVolume.store(streamVolume);
431     return true;
432 }
433 
GetDuckFactor()434 float OHAudioBuffer::GetDuckFactor()
435 {
436     CHECK_AND_RETURN_RET_LOG(basicBufferInfo_ != nullptr, MAX_FLOAT_VOLUME, "buffer is not inited!");
437     float factor = basicBufferInfo_->duckFactor.load();
438     if (factor < MIN_FLOAT_VOLUME) {
439         AUDIO_WARNING_LOG("vol < 0.0, invalid duckFactor! using 0.0 instead.");
440         return MIN_FLOAT_VOLUME;
441     } else if (factor > MAX_FLOAT_VOLUME) {
442         AUDIO_WARNING_LOG("vol > 0.0, invalid duckFactor! using 1.0 instead.");
443         return MAX_FLOAT_VOLUME;
444     }
445     return factor;
446 }
447 
SetDuckFactor(float duckFactor)448 bool OHAudioBuffer::SetDuckFactor(float duckFactor)
449 {
450     CHECK_AND_RETURN_RET_LOG(basicBufferInfo_ != nullptr, false, "buffer is not inited!");
451     if (duckFactor < MIN_FLOAT_VOLUME || duckFactor > MAX_FLOAT_VOLUME) {
452         AUDIO_ERR_LOG("invlaid factor:%{public}f", duckFactor);
453         return false;
454     }
455     basicBufferInfo_->duckFactor.store(duckFactor);
456     return true;
457 }
458 
459 
GetUnderrunCount()460 uint32_t OHAudioBuffer::GetUnderrunCount()
461 {
462     CHECK_AND_RETURN_RET_LOG(basicBufferInfo_ != nullptr, 0,
463         "Get nullptr, buffer is not inited.");
464     return basicBufferInfo_->underrunCount.load();
465 }
466 
SetUnderrunCount(uint32_t count)467 bool OHAudioBuffer::SetUnderrunCount(uint32_t count)
468 {
469     CHECK_AND_RETURN_RET_LOG(basicBufferInfo_ != nullptr, false,
470         "Get nullptr, buffer is not inited.");
471     basicBufferInfo_->underrunCount.store(count);
472     return true;
473 }
474 
GetHandleInfo(uint64_t & frames,int64_t & nanoTime)475 bool OHAudioBuffer::GetHandleInfo(uint64_t &frames, int64_t &nanoTime)
476 {
477     CHECK_AND_RETURN_RET_LOG(basicBufferInfo_ != nullptr, false,
478         "Get nullptr, failed to GetHandleInfo.");
479 
480     frames = basicBufferInfo_->handlePos.load();
481     nanoTime = basicBufferInfo_->handleTime.load();
482     return true;
483 }
484 
SetHandleInfo(uint64_t frames,int64_t nanoTime)485 void OHAudioBuffer::SetHandleInfo(uint64_t frames, int64_t nanoTime)
486 {
487     basicBufferInfo_->handlePos.store(frames);
488     basicBufferInfo_->handleTime.store(nanoTime);
489 }
490 
GetAvailableDataFrames()491 int32_t OHAudioBuffer::GetAvailableDataFrames()
492 {
493     int32_t result = -1; // failed
494     uint64_t write = basicBufferInfo_->curWriteFrame.load();
495     uint64_t read = basicBufferInfo_->curReadFrame.load();
496     CHECK_AND_RETURN_RET_LOG(write >= read, result, "invalid write and read position.");
497     uint32_t temp = write - read;
498     CHECK_AND_RETURN_RET_LOG(temp <= INT32_MAX && temp <= totalSizeInFrame_,
499         result, "failed to GetAvailableDataFrames.");
500     result = static_cast<int32_t>(totalSizeInFrame_ - temp);
501     return result;
502 }
503 
ResetCurReadWritePos(uint64_t readFrame,uint64_t writeFrame)504 int32_t OHAudioBuffer::ResetCurReadWritePos(uint64_t readFrame, uint64_t writeFrame)
505 {
506     CHECK_AND_RETURN_RET_LOG(readFrame <= writeFrame && writeFrame - readFrame < totalSizeInFrame_,
507         ERR_INVALID_PARAM, "Invalid read or write position:read%{public}" PRIu64" write%{public}" PRIu64".",
508         readFrame, writeFrame);
509     uint64_t tempBase = (readFrame / totalSizeInFrame_) * totalSizeInFrame_;
510     basicBufferInfo_->basePosInFrame.store(tempBase);
511     basicBufferInfo_->curWriteFrame.store(writeFrame);
512     basicBufferInfo_->curReadFrame.store(readFrame);
513 
514     AUDIO_DEBUG_LOG("Reset position:read%{public}" PRIu64" write%{public}" PRIu64".", readFrame, writeFrame);
515     return SUCCESS;
516 }
517 
GetCurWriteFrame()518 uint64_t OHAudioBuffer::GetCurWriteFrame()
519 {
520     CHECK_AND_RETURN_RET_LOG(basicBufferInfo_ != nullptr, 0, "basicBufferInfo_ is null");
521     return basicBufferInfo_->curWriteFrame.load();
522 }
523 
GetCurReadFrame()524 uint64_t OHAudioBuffer::GetCurReadFrame()
525 {
526     CHECK_AND_RETURN_RET_LOG(basicBufferInfo_ != nullptr, 0, "basicBufferInfo_ is null");
527     return basicBufferInfo_->curReadFrame.load();
528 }
529 
SetCurWriteFrame(uint64_t writeFrame)530 int32_t OHAudioBuffer::SetCurWriteFrame(uint64_t writeFrame)
531 {
532     uint64_t basePos = basicBufferInfo_->basePosInFrame.load();
533     uint64_t oldWritePos = basicBufferInfo_->curWriteFrame.load();
534     if (writeFrame == oldWritePos) {
535         return SUCCESS;
536     }
537     CHECK_AND_RETURN_RET_LOG(writeFrame > oldWritePos, ERR_INVALID_PARAM, "Too small writeFrame:%{public}" PRIu64".",
538         writeFrame);
539 
540     uint64_t deltaToBase = writeFrame - basePos; // writeFrame % spanSizeInFrame_ --> 0
541     CHECK_AND_RETURN_RET_LOG(deltaToBase / spanSizeInFrame_ * spanSizeInFrame_ == deltaToBase, ERR_INVALID_PARAM,
542         "Invalid deltaToBase, writeFrame:%{public}" PRIu64".", writeFrame);
543 
544     // check new pos in range: base ~ base + 2*total
545     CHECK_AND_RETURN_RET_LOG(deltaToBase < (totalSizeInFrame_ + totalSizeInFrame_),
546         ERR_INVALID_PARAM, "Invalid writeFrame %{public}" PRIu64" out of base range.", writeFrame);
547 
548     // check new pos in (read + cache) range: read ~ read + totalSize - 1*spanSize
549     uint64_t curRead = basicBufferInfo_->curReadFrame.load();
550     CHECK_AND_RETURN_RET_LOG(writeFrame >= curRead && writeFrame - curRead <= totalSizeInFrame_,
551         ERR_INVALID_PARAM, "Invalid writeFrame %{public}" PRIu64" out of cache range, curRead %{public}" PRIu64".",
552         writeFrame, curRead);
553 
554     if (writeFrame - oldWritePos != spanSizeInFrame_) {
555         AUDIO_WARNING_LOG("Not advanced in one step. newWritePos %{public}" PRIu64", oldWritePos %{public}" PRIu64".",
556             writeFrame, oldWritePos);
557     }
558 
559     basicBufferInfo_->curWriteFrame.store(writeFrame);
560     return SUCCESS;
561 }
562 
SetCurReadFrame(uint64_t readFrame)563 int32_t OHAudioBuffer::SetCurReadFrame(uint64_t readFrame)
564 {
565     CHECK_AND_RETURN_RET_LOG(basicBufferInfo_ != nullptr, ERR_INVALID_PARAM, "basicBufferInfo_ is nullptr");
566     uint64_t oldBasePos = basicBufferInfo_->basePosInFrame.load();
567     uint64_t oldReadPos = basicBufferInfo_->curReadFrame.load();
568     if (readFrame == oldReadPos) {
569         return SUCCESS;
570     }
571 
572     // new read position should not be bigger than write position or less than old read position
573     CHECK_AND_RETURN_RET_LOG(readFrame >= oldReadPos && readFrame <= basicBufferInfo_->curWriteFrame.load(),
574         ERR_INVALID_PARAM, "Invalid readFrame %{public}" PRIu64".", readFrame);
575 
576     uint64_t deltaToBase = readFrame - oldBasePos;
577     CHECK_AND_RETURN_RET_LOG((deltaToBase / spanSizeInFrame_ * spanSizeInFrame_) == deltaToBase,
578         ERR_INVALID_PARAM, "Invalid deltaToBase, readFrame %{public}" PRIu64", oldBasePos %{public}" PRIu64".",
579             readFrame, oldBasePos);
580 
581     if (deltaToBase > totalSizeInFrame_) {
582         AUDIO_ERR_LOG("Invalid readFrame:%{public}" PRIu64", out of range.", readFrame);
583         return ERR_INVALID_PARAM;
584     } else if (deltaToBase == totalSizeInFrame_) {
585         basicBufferInfo_->basePosInFrame.store(oldBasePos + totalSizeInFrame_); // move base position
586     }
587 
588     if (readFrame - oldReadPos != spanSizeInFrame_) {
589         AUDIO_WARNING_LOG("Not advanced in one step. newReadPos %{public}" PRIu64", oldReadPos %{public}" PRIu64".",
590             readFrame, oldReadPos);
591     }
592 
593     basicBufferInfo_->curReadFrame.store(readFrame);
594     return SUCCESS;
595 }
596 
GetBufferByFrame(uint64_t posInFrame,BufferDesc & bufferDesc)597 int32_t OHAudioBuffer::GetBufferByFrame(uint64_t posInFrame, BufferDesc &bufferDesc)
598 {
599     uint64_t basePos = basicBufferInfo_->basePosInFrame.load();
600     uint64_t maxDelta = 2 * totalSizeInFrame_; // 0 ~ 2*totalSizeInFrame_
601     CHECK_AND_RETURN_RET_LOG(posInFrame >= basePos && posInFrame - basePos < maxDelta,
602         ERR_INVALID_PARAM, "Invalid position:%{public}" PRIu64".", posInFrame);
603 
604     uint32_t deltaToBase = posInFrame - basePos;
605     if (deltaToBase >= totalSizeInFrame_) {
606         deltaToBase -= totalSizeInFrame_;
607     }
608     CHECK_AND_RETURN_RET_LOG(deltaToBase < UINT32_MAX && deltaToBase < totalSizeInFrame_, ERR_INVALID_PARAM,
609         "invalid deltaToBase, posInFrame %{public}" PRIu64" basePos %{public}" PRIu64".", posInFrame, basePos);
610     deltaToBase = (deltaToBase / spanSizeInFrame_) * spanSizeInFrame_;
611     size_t offset = deltaToBase * byteSizePerFrame_;
612     CHECK_AND_RETURN_RET_LOG(offset < totalSizeInByte_, ERR_INVALID_PARAM, "invalid deltaToBase:%{public}zu", offset);
613     bufferDesc.buffer = dataBase_ + offset;
614     bufferDesc.bufLength = spanSizeInByte_;
615     bufferDesc.dataLength = spanSizeInByte_;
616 
617     return SUCCESS;
618 }
619 
GetSessionId()620 uint32_t OHAudioBuffer::GetSessionId()
621 {
622     return sessionId_;
623 }
624 
SetSessionId(uint32_t sessionId)625 int32_t OHAudioBuffer::SetSessionId(uint32_t sessionId)
626 {
627     sessionId_ = sessionId;
628 
629     return SUCCESS;
630 }
631 
GetWriteBuffer(uint64_t writePosInFrame,BufferDesc & bufferDesc)632 int32_t OHAudioBuffer::GetWriteBuffer(uint64_t writePosInFrame, BufferDesc &bufferDesc)
633 {
634     uint64_t basePos = basicBufferInfo_->basePosInFrame.load();
635     uint64_t readPos = basicBufferInfo_->curReadFrame.load();
636     uint64_t maxWriteDelta = 2 * totalSizeInFrame_; // 0 ~ 2*totalSizeInFrame_
637     CHECK_AND_RETURN_RET_LOG(writePosInFrame >= basePos && writePosInFrame - basePos < maxWriteDelta &&
638         writePosInFrame >= readPos, ERR_INVALID_PARAM, "Invalid write position:%{public}" PRIu64".", writePosInFrame);
639     return GetBufferByFrame(writePosInFrame, bufferDesc);
640 }
641 
GetReadbuffer(uint64_t readPosInFrame,BufferDesc & bufferDesc)642 int32_t OHAudioBuffer::GetReadbuffer(uint64_t readPosInFrame, BufferDesc &bufferDesc)
643 {
644     uint64_t basePos = basicBufferInfo_->basePosInFrame.load();
645     CHECK_AND_RETURN_RET_LOG(readPosInFrame >= basePos && readPosInFrame - basePos < totalSizeInFrame_,
646         ERR_INVALID_PARAM, "Invalid read position:%{public}" PRIu64".", readPosInFrame);
647     return GetBufferByFrame(readPosInFrame, bufferDesc);
648 }
649 
GetSpanInfo(uint64_t posInFrame)650 SpanInfo *OHAudioBuffer::GetSpanInfo(uint64_t posInFrame)
651 {
652     uint64_t basePos = basicBufferInfo_->basePosInFrame.load();
653     uint64_t maxPos = basePos + totalSizeInFrame_ + totalSizeInFrame_;
654     CHECK_AND_RETURN_RET_LOG((basePos <= posInFrame && posInFrame < maxPos), nullptr, "posInFrame %{public}" PRIu64" "
655         "out of range, basePos %{public}" PRIu64", maxPos %{public}" PRIu64".", posInFrame, basePos, maxPos);
656 
657     uint64_t deltaToBase = posInFrame - basePos;
658     if (deltaToBase >= totalSizeInFrame_) {
659         deltaToBase -= totalSizeInFrame_;
660     }
661     CHECK_AND_RETURN_RET_LOG(deltaToBase < UINT32_MAX && deltaToBase < totalSizeInFrame_, nullptr,"invalid "
662         "deltaToBase, posInFrame %{public}"  PRIu64" basePos %{public}" PRIu64".", posInFrame, basePos);
663 
664     if (spanSizeInFrame_ > 0) {
665         uint32_t spanIndex = deltaToBase / spanSizeInFrame_;
666         CHECK_AND_RETURN_RET_LOG(spanIndex < spanConut_, nullptr, "invalid spanIndex:%{public}d", spanIndex);
667         return &spanInfoList_[spanIndex];
668     }
669     return nullptr;
670 }
671 
GetSpanInfoByIndex(uint32_t spanIndex)672 SpanInfo *OHAudioBuffer::GetSpanInfoByIndex(uint32_t spanIndex)
673 {
674     CHECK_AND_RETURN_RET_LOG(spanIndex < spanConut_, nullptr, "invalid spanIndex:%{public}d", spanIndex);
675     return &spanInfoList_[spanIndex];
676 }
677 
GetSpanCount()678 uint32_t OHAudioBuffer::GetSpanCount()
679 {
680     return spanConut_;
681 }
682 
GetLastWrittenTime()683 int64_t OHAudioBuffer::GetLastWrittenTime()
684 {
685     return lastWrittenTime_;
686 }
687 
SetLastWrittenTime(int64_t time)688 void OHAudioBuffer::SetLastWrittenTime(int64_t time)
689 {
690     lastWrittenTime_ = time;
691 }
692 
GetFutex()693 std::atomic<uint32_t> *OHAudioBuffer::GetFutex()
694 {
695     return &basicBufferInfo_->futexObj;
696 }
697 
GetDataBase()698 uint8_t *OHAudioBuffer::GetDataBase()
699 {
700     return dataBase_;
701 }
702 
GetDataSize()703 size_t OHAudioBuffer::GetDataSize()
704 {
705     return totalSizeInByte_;
706 }
707 
708 } // namespace AudioStandard
709 } // namespace OHOS
710