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