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