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
16 #include "audio_process_in_server.h"
17
18 #include "securec.h"
19
20 #include "audio_errors.h"
21 #include "audio_log.h"
22
23 namespace OHOS {
24 namespace AudioStandard {
25 namespace {
26 static constexpr int32_t VOLUME_SHIFT_NUMBER = 16; // 1 >> 16 = 65536, max volume
27 }
28
Create(const AudioProcessConfig & processConfig,ProcessReleaseCallback * releaseCallback)29 sptr<AudioProcessInServer> AudioProcessInServer::Create(const AudioProcessConfig &processConfig,
30 ProcessReleaseCallback *releaseCallback)
31 {
32 sptr<AudioProcessInServer> process = new(std::nothrow) AudioProcessInServer(processConfig, releaseCallback);
33
34 return process;
35 }
36
AudioProcessInServer(const AudioProcessConfig & processConfig,ProcessReleaseCallback * releaseCallback)37 AudioProcessInServer::AudioProcessInServer(const AudioProcessConfig &processConfig,
38 ProcessReleaseCallback *releaseCallback) : processConfig_(processConfig), releaseCallback_(releaseCallback)
39 {
40 AUDIO_INFO_LOG("AudioProcessInServer()");
41 }
42
~AudioProcessInServer()43 AudioProcessInServer::~AudioProcessInServer()
44 {
45 AUDIO_INFO_LOG("~AudioProcessInServer()");
46 }
47
ResolveBuffer(std::shared_ptr<OHAudioBuffer> & buffer)48 int32_t AudioProcessInServer::ResolveBuffer(std::shared_ptr<OHAudioBuffer> &buffer)
49 {
50 if (!isBufferConfiged_) {
51 AUDIO_ERR_LOG("ResolveBuffer failed, buffer is not configed.");
52 return ERR_ILLEGAL_STATE;
53 }
54
55 buffer = processBuffer_;
56 CHECK_AND_RETURN_RET_LOG(buffer != nullptr, ERR_ILLEGAL_STATE, "ResolveBuffer failed, processBuffer_ is null.");
57
58 return SUCCESS;
59 }
60
RequestHandleInfo()61 int32_t AudioProcessInServer::RequestHandleInfo()
62 {
63 CHECK_AND_RETURN_RET_LOG(isInited_, ERR_ILLEGAL_STATE, "not inited!");
64 CHECK_AND_RETURN_RET_LOG(processBuffer_ != nullptr, ERR_ILLEGAL_STATE, "buffer not inited!");
65
66 for (size_t i = 0; i < listenerList_.size(); i++) {
67 listenerList_[i]->OnUpdateHandleInfo(this);
68 }
69 return SUCCESS;
70 }
71
Start()72 int32_t AudioProcessInServer::Start()
73 {
74 CHECK_AND_RETURN_RET_LOG(isInited_, ERR_ILLEGAL_STATE, "not inited!");
75 std::lock_guard<std::mutex> lock(statusLock_);
76 if (streamStatus_->load() != STREAM_STARTING) {
77 AUDIO_ERR_LOG("Start failed, invalid status.");
78 return ERR_ILLEGAL_STATE;
79 }
80
81 for (size_t i = 0; i < listenerList_.size(); i++) {
82 listenerList_[i]->OnStart(this);
83 }
84
85 AUDIO_INFO_LOG("Start in server success!");
86 return SUCCESS;
87 }
88
Pause(bool isFlush)89 int32_t AudioProcessInServer::Pause(bool isFlush)
90 {
91 CHECK_AND_RETURN_RET_LOG(isInited_, ERR_ILLEGAL_STATE, "not inited!");
92
93 (void)isFlush;
94 std::lock_guard<std::mutex> lock(statusLock_);
95 if (streamStatus_->load() != STREAM_PAUSING) {
96 AUDIO_ERR_LOG("Pause failed, invalid status.");
97 return ERR_ILLEGAL_STATE;
98 }
99
100 for (size_t i = 0; i < listenerList_.size(); i++) {
101 listenerList_[i]->OnPause(this);
102 }
103
104 AUDIO_INFO_LOG("Pause in server success!");
105 return SUCCESS;
106 }
107
Resume()108 int32_t AudioProcessInServer::Resume()
109 {
110 CHECK_AND_RETURN_RET_LOG(isInited_, ERR_ILLEGAL_STATE, "not inited!");
111 std::lock_guard<std::mutex> lock(statusLock_);
112 if (streamStatus_->load() != STREAM_STARTING) {
113 AUDIO_ERR_LOG("Resume failed, invalid status.");
114 return ERR_ILLEGAL_STATE;
115 }
116
117 for (size_t i = 0; i < listenerList_.size(); i++) {
118 listenerList_[i]->OnStart(this);
119 }
120
121 AUDIO_INFO_LOG("Resume in server success!");
122 return SUCCESS;
123 }
124
Stop()125 int32_t AudioProcessInServer::Stop()
126 {
127 CHECK_AND_RETURN_RET_LOG(isInited_, ERR_ILLEGAL_STATE, "not inited!");
128
129 std::lock_guard<std::mutex> lock(statusLock_);
130 if (streamStatus_->load() != STREAM_STOPPING) {
131 AUDIO_ERR_LOG("Stop failed, invalid status.");
132 return ERR_ILLEGAL_STATE;
133 }
134
135 for (size_t i = 0; i < listenerList_.size(); i++) {
136 listenerList_[i]->OnPause(this); // notify endpoint?
137 }
138
139 AUDIO_INFO_LOG("Stop in server success!");
140 return SUCCESS;
141 }
142
Release()143 int32_t AudioProcessInServer::Release()
144 {
145 CHECK_AND_RETURN_RET_LOG(isInited_, ERR_ILLEGAL_STATE, "not inited or already released");
146
147 isInited_ = false;
148 std::lock_guard<std::mutex> lock(statusLock_);
149 CHECK_AND_RETURN_RET_LOG(releaseCallback_ != nullptr, ERR_OPERATION_FAILED, "Failed: no service to notify.");
150
151 int32_t ret = releaseCallback_->OnProcessRelease(this);
152 AUDIO_INFO_LOG("notify service release result: %{public}d", ret);
153 return SUCCESS;
154 }
155
ProcessDeathRecipient(AudioProcessInServer * processInServer,ProcessReleaseCallback * processHolder)156 ProcessDeathRecipient::ProcessDeathRecipient(AudioProcessInServer *processInServer,
157 ProcessReleaseCallback *processHolder)
158 {
159 processInServer_ = processInServer;
160 processHolder_ = processHolder;
161 }
162
OnRemoteDied(const wptr<IRemoteObject> & remote)163 void ProcessDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
164 {
165 CHECK_AND_RETURN_LOG(processHolder_ != nullptr, "processHolder_ is null.");
166 int32_t ret = processHolder_->OnProcessRelease(processInServer_);
167 AUDIO_INFO_LOG("OnRemoteDied, call release ret: %{public}d", ret);
168 }
169
RegisterProcessCb(sptr<IRemoteObject> object)170 int32_t AudioProcessInServer::RegisterProcessCb(sptr<IRemoteObject> object)
171 {
172 sptr<IProcessCb> processCb = iface_cast<IProcessCb>(object);
173 CHECK_AND_RETURN_RET_LOG(processCb != nullptr, ERR_INVALID_PARAM, "RegisterProcessCb obj cast failed");
174 bool result = object->AddDeathRecipient(new ProcessDeathRecipient(this, releaseCallback_));
175 if (!result) {
176 AUDIO_ERR_LOG("AddDeathRecipient failed.");
177 return ERR_OPERATION_FAILED;
178 }
179
180 return SUCCESS;
181 }
182
Dump(int fd,const std::vector<std::u16string> & args)183 int AudioProcessInServer::Dump(int fd, const std::vector<std::u16string> &args)
184 {
185 return SUCCESS;
186 }
187
Dump(std::stringstream & dumpStringStream)188 void AudioProcessInServer::Dump(std::stringstream &dumpStringStream)
189 {
190 dumpStringStream << std::endl << "uid:" << processConfig_.appInfo.appUid;
191 dumpStringStream << " pid:" << processConfig_.appInfo.appPid << std::endl;
192 dumpStringStream << " process info:" << std::endl;
193 dumpStringStream << " stream info:" << std::endl;
194 dumpStringStream << " samplingRate:" << processConfig_.streamInfo.samplingRate << std::endl;
195 dumpStringStream << " channels:" << processConfig_.streamInfo.channels << std::endl;
196 dumpStringStream << " format:" << processConfig_.streamInfo.format << std::endl;
197 dumpStringStream << " encoding:" << processConfig_.streamInfo.encoding << std::endl;
198 if (streamStatus_ != nullptr) {
199 dumpStringStream << "Status:" << streamStatus_->load() << std::endl;
200 }
201 dumpStringStream << std::endl;
202 }
203
GetStreamBuffer()204 std::shared_ptr<OHAudioBuffer> AudioProcessInServer::GetStreamBuffer()
205 {
206 if (!isBufferConfiged_ || processBuffer_ == nullptr) {
207 AUDIO_ERR_LOG("GetStreamBuffer failed:process buffer not config.");
208 return nullptr;
209 }
210 return processBuffer_;
211 }
212
GetStreamInfo()213 AudioStreamInfo AudioProcessInServer::GetStreamInfo()
214 {
215 return processConfig_.streamInfo;
216 }
217
GetAudioStreamType()218 AudioStreamType AudioProcessInServer::GetAudioStreamType()
219 {
220 return processConfig_.streamType;
221 }
222
PcmFormatToBits(AudioSampleFormat format)223 inline uint32_t PcmFormatToBits(AudioSampleFormat format)
224 {
225 switch (format) {
226 case SAMPLE_U8:
227 return 1; // 1 byte
228 case SAMPLE_S16LE:
229 return 2; // 2 byte
230 case SAMPLE_S24LE:
231 return 3; // 3 byte
232 case SAMPLE_S32LE:
233 return 4; // 4 byte
234 case SAMPLE_F32LE:
235 return 4; // 4 byte
236 default:
237 return 2; // 2 byte
238 }
239 }
240
InitBufferStatus()241 int32_t AudioProcessInServer::InitBufferStatus()
242 {
243 if (processBuffer_ == nullptr) {
244 AUDIO_ERR_LOG("InitBufferStatus failed, null buffer.");
245 return ERR_ILLEGAL_STATE;
246 }
247
248 uint32_t spanCount = processBuffer_->GetSpanCount();
249 for (uint32_t i = 0; i < spanCount; i++) {
250 SpanInfo *spanInfo = processBuffer_->GetSpanInfoByIndex(i);
251 if (spanInfo == nullptr) {
252 AUDIO_ERR_LOG("InitBufferStatus failed, null spaninfo");
253 return ERR_ILLEGAL_STATE;
254 }
255 spanInfo->spanStatus = SPAN_READ_DONE;
256 spanInfo->offsetInFrame = 0;
257
258 spanInfo->readStartTime = 0;
259 spanInfo->readDoneTime = 0;
260
261 spanInfo->writeStartTime = 0;
262 spanInfo->writeDoneTime = 0;
263
264 spanInfo->volumeStart = 1 << VOLUME_SHIFT_NUMBER; // 65536 for initialize
265 spanInfo->volumeEnd = 1 << VOLUME_SHIFT_NUMBER; // 65536 for initialize
266 spanInfo->isMute = false;
267 }
268 return SUCCESS;
269 }
270
ConfigProcessBuffer(uint32_t & totalSizeInframe,uint32_t & spanSizeInframe)271 int32_t AudioProcessInServer::ConfigProcessBuffer(uint32_t &totalSizeInframe, uint32_t &spanSizeInframe)
272 {
273 if (processBuffer_ != nullptr) {
274 AUDIO_INFO_LOG("ConfigProcessBuffer: process buffer already configed!");
275 return SUCCESS;
276 }
277 // check
278 if (totalSizeInframe == 0 || spanSizeInframe == 0 || totalSizeInframe % spanSizeInframe != 0) {
279 AUDIO_ERR_LOG("ConfigProcessBuffer failed: ERR_INVALID_PARAM");
280 return ERR_INVALID_PARAM;
281 }
282 totalSizeInframe_ = totalSizeInframe;
283 spanSizeInframe_ = spanSizeInframe;
284
285 uint32_t channel = processConfig_.streamInfo.channels;
286 uint32_t formatbyte = PcmFormatToBits(processConfig_.streamInfo.format);
287 byteSizePerFrame_ = channel * formatbyte;
288
289 // create OHAudioBuffer in server.
290 processBuffer_ = OHAudioBuffer::CreateFormLocal(totalSizeInframe_, spanSizeInframe_, byteSizePerFrame_);
291 CHECK_AND_RETURN_RET_LOG(processBuffer_ != nullptr, ERR_OPERATION_FAILED, "Create process buffer failed.");
292
293 if (processBuffer_->GetBufferHolder() != AudioBufferHolder::AUDIO_SERVER_SHARED) {
294 AUDIO_ERR_LOG("CreateFormLocal in server failed.");
295 return ERR_ILLEGAL_STATE;
296 }
297 AUDIO_INFO_LOG("Config: totalSizeInframe:%{public}d spanSizeInframe:%{public}d byteSizePerFrame:%{public}d",
298 totalSizeInframe_, spanSizeInframe_, byteSizePerFrame_);
299
300 // we need to clear data buffer to avoid dirty data.
301 memset_s(processBuffer_->GetDataBase(), processBuffer_->GetDataSize(), 0, processBuffer_->GetDataSize());
302 int32_t ret = InitBufferStatus();
303 AUDIO_DEBUG_LOG("clear data buffer, ret:%{public}d", ret);
304
305 streamStatus_ = processBuffer_->GetStreamStatus();
306 CHECK_AND_RETURN_RET_LOG(streamStatus_ != nullptr, ERR_OPERATION_FAILED, "Create process buffer failed.");
307 isBufferConfiged_ = true;
308 isInited_ = true;
309 return SUCCESS;
310 }
311
AddProcessStatusListener(std::shared_ptr<IProcessStatusListener> listener)312 int32_t AudioProcessInServer::AddProcessStatusListener(std::shared_ptr<IProcessStatusListener> listener)
313 {
314 std::lock_guard<std::mutex> lock(listenerListLock_);
315 listenerList_.push_back(listener);
316 return SUCCESS;
317 }
318
RemoveProcessStatusListener(std::shared_ptr<IProcessStatusListener> listener)319 int32_t AudioProcessInServer::RemoveProcessStatusListener(std::shared_ptr<IProcessStatusListener> listener)
320 {
321 std::lock_guard<std::mutex> lock(listenerListLock_);
322 std::vector<std::shared_ptr<IProcessStatusListener>>::iterator it = listenerList_.begin();
323 bool isFind = false;
324 while (it != listenerList_.end()) {
325 if (*it == listener) {
326 listenerList_.erase(it);
327 isFind = true;
328 break;
329 } else {
330 it++;
331 }
332 }
333
334 AUDIO_INFO_LOG("%{public}s the endpoint.", (isFind ? "find and remove" : "not find"));
335 return SUCCESS;
336 }
337 } // namespace AudioStandard
338 } // namespace OHOS
339