• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024-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 "TonePlayerImpl"
17 #endif
18 
19 #include <sys/time.h>
20 #include <utility>
21 
22 #include <climits>
23 #include <cmath>
24 #include <cfloat>
25 #include "securec.h"
26 #include "audio_common_log.h"
27 #include "audio_policy_manager.h"
28 #include "tone_player_impl.h"
29 #include "audio_utils.h"
30 #include "audio_errors.h"
31 #include "parameter.h"
32 #ifdef AUDIO_TEL_CORE_SERVICE_ENABLE
33 #include "core_service_client.h"
34 #endif
35 #ifdef AUIDO_TEL_CELLULAR_DATA_ENABLE
36 #include "cellular_data_client.h"
37 #endif
38 
39 namespace OHOS {
40 namespace AudioStandard {
41 namespace {
42 constexpr int32_t C20MS = 20;
43 constexpr int32_t C1000MS = 1000;
44 constexpr int32_t CDOUBLE = 2;
45 constexpr int32_t DIGITAMPLITUDE = 800;
46 constexpr int32_t AMPLITUDE = 8000;
47 constexpr int32_t BIT8 = 8;
48 constexpr int32_t SYSPARA_SIZE = 128;
49 const char DEBUG_COUNTRYCODE_NAME[] = "debug.toneplayer.country";
50 const char DEFAULT_STRING[] = "error";
51 const char DUMP_TONEPLAYER_FILENAME[] = "dump_toneplayer_audio.pcm";
52 
53 static const std::vector<ToneType> TONE_TYPE_LIST = {
54     TONE_TYPE_DIAL_0,
55     TONE_TYPE_DIAL_1,
56     TONE_TYPE_DIAL_2,
57     TONE_TYPE_DIAL_3,
58     TONE_TYPE_DIAL_4,
59     TONE_TYPE_DIAL_5,
60     TONE_TYPE_DIAL_6,
61     TONE_TYPE_DIAL_7,
62     TONE_TYPE_DIAL_8,
63     TONE_TYPE_DIAL_9,
64     TONE_TYPE_DIAL_S,
65     TONE_TYPE_DIAL_P
66 };
67 }
68 
TonePlayerImpl(const std::string cachePath,const AudioRendererInfo & rendereInfo)69 TonePlayerImpl::TonePlayerImpl(const std::string cachePath, const AudioRendererInfo &rendereInfo)
70 {
71     toneState_ = TONE_IDLE;
72     rendererOptions_.streamInfo.encoding = AudioEncodingType::ENCODING_PCM;
73     rendererOptions_.streamInfo.samplingRate = SAMPLE_RATE_48000;
74     rendererOptions_.streamInfo.format = SAMPLE_S16LE;
75     rendererOptions_.streamInfo.channels = MONO;
76 
77     // contentType::CONTENT_TYPE_MUSIC;
78     rendererOptions_.rendererInfo.contentType = rendereInfo.contentType;
79 
80     // streamUsage::STREAM_USAGE_MEDIA;
81     rendererOptions_.rendererInfo.streamUsage = rendereInfo.streamUsage;
82     rendererOptions_.rendererInfo.rendererFlags = AUDIO_FLAG_FORCED_NORMAL; // use AUDIO_FLAG_FORCED_NORMAL
83 
84     rendererOptions_.strategy = { AudioConcurrencyMode::MIX_WITH_OTHERS };
85     supportedTones_ = AudioPolicyManager::GetInstance().GetSupportedTones(GetCountryCode());
86     toneInfo_ = NULL;
87     initialToneInfo_ = NULL;
88     samplingRate_ = rendererOptions_.streamInfo.samplingRate;
89 }
90 
~TonePlayerImpl()91 TonePlayerImpl::~TonePlayerImpl()
92 {
93     AUDIO_INFO_LOG("TonePlayerImpl destructor");
94     if (audioRenderer_ != nullptr) {
95         audioRenderer_->Stop();
96         audioRenderer_->Release();
97     }
98     audioRenderer_ = nullptr;
99 }
100 
Create(const AudioRendererInfo & rendererInfo)101 std::shared_ptr<TonePlayer> TonePlayer::Create(const AudioRendererInfo &rendererInfo)
102 {
103     if (!PermissionUtil::VerifySelfPermission()) {
104         AUDIO_ERR_LOG("Create: No system permission");
105         return nullptr;
106     }
107     return std::make_shared<TonePlayerImpl>("", rendererInfo);
108 }
109 
Create(const std::string cachePath,const AudioRendererInfo & rendererInfo)110 std::shared_ptr<TonePlayer> TonePlayer::Create(const std::string cachePath, const AudioRendererInfo &rendererInfo)
111 {
112     bool checkPermission = PermissionUtil::VerifySelfPermission();
113     CHECK_AND_RETURN_RET_LOG(checkPermission, nullptr, "Create: No system permission");
114     return std::make_shared<TonePlayerImpl>(cachePath, rendererInfo);
115 }
116 
OnInterrupt(const InterruptEvent & interruptEvent)117 void TonePlayerImpl::OnInterrupt(const InterruptEvent &interruptEvent)
118 {
119     AUDIO_INFO_LOG("ToneType %{public}d eventType: %{public}d", toneType_, interruptEvent.eventType);
120     return;
121 }
122 
OnStateChange(const RendererState state,const StateChangeCmdType cmdType)123 void TonePlayerImpl::OnStateChange(const RendererState state, const StateChangeCmdType __attribute__((unused)) cmdType)
124 {
125     AUDIO_INFO_LOG("ToneType %{public}d  OnStateChange state: %{public}d", toneType_, state);
126 }
127 
OnWriteData(size_t length)128 void TonePlayerImpl::OnWriteData(size_t length)
129 {
130     std::lock_guard<std::mutex> lock(optMutex_);
131     if (toneState_ == TONE_RELEASED) {
132         AUDIO_WARNING_LOG("Tone %{public}d is already released", toneType_);
133         return;
134     }
135     BufferDesc bufDesc = {};
136     if (audioRenderer_ != nullptr) {
137         audioRenderer_->GetBufferDesc(bufDesc);
138     } else {
139         AUDIO_ERR_LOG("OnWriteData audioRenderer_ is null");
140     }
141     bufDesc.dataLength = 0;
142     if (bufDesc.bufLength == 0) {
143         AUDIO_WARNING_LOG(" bufDesc bufLength is 0");
144         return;
145     }
146 
147     // Clear output buffer: WaveGenerator accumulates into audioBuffer buffer
148     memset_s(bufDesc.buffer, bufDesc.bufLength, 0, bufDesc.bufLength);
149     if (AudioToneSequenceGen(bufDesc) == false) {
150         AUDIO_WARNING_LOG("SequenceGen error");
151         bufDesc.dataLength = bufDesc.bufLength;
152     }
153     DumpFileUtil::WriteDumpFile(dumpFile_, static_cast<void *>(bufDesc.buffer), bufDesc.dataLength);
154     if (audioRenderer_ != nullptr) {
155         audioRenderer_->Enqueue(bufDesc);
156     } else {
157         AUDIO_ERR_LOG("AudioToneDataThreadFunc Enqueue audioRenderer_ is null");
158     }
159 }
160 
LoadTone(ToneType toneType)161 bool TonePlayerImpl::LoadTone(ToneType toneType)
162 {
163     std::lock_guard<std::mutex> lock(optMutex_);
164     AUDIO_INFO_LOG("LoadTone type: %{public}d", toneType);
165     bool result = false;
166     bool checkPermission = PermissionUtil::VerifySelfPermission();
167     CHECK_AND_RETURN_RET_LOG(checkPermission, false, "LoadTone: No system permission");
168     if (toneType >= NUM_TONES) {
169         return result;
170     }
171     if (std::find(supportedTones_.begin(), supportedTones_.end(), (int32_t)toneType) == supportedTones_.end()) {
172         return result;
173     }
174     toneType_ = toneType;
175     amplitudeType_ = std::count(TONE_TYPE_LIST.begin(), TONE_TYPE_LIST.end(), toneType_) > 0 ?
176         DIGITAMPLITUDE : AMPLITUDE;
177     initialToneInfo_ = AudioPolicyManager::GetInstance().GetToneConfig(toneType, GetCountryCode());
178     if (initialToneInfo_->segmentCnt == 0) {
179         AUDIO_ERR_LOG("LoadTone failed, calling GetToneConfig returned invalid");
180         return result;
181     }
182     if (!isRendererInited_) {
183         isRendererInited_ = InitAudioRenderer();
184         CHECK_AND_RETURN_RET_LOG(isRendererInited_, false, "InitAudioRenderer failed");
185     }
186     result = InitToneWaveInfo();
187     CHECK_AND_RETURN_RET_LOG(result, false, "InitToneWaveInfo failed");
188     toneState_ = TONE_INIT;
189     DumpFileUtil::OpenDumpFile(DumpFileUtil::DUMP_CLIENT_PARA, DUMP_TONEPLAYER_FILENAME, &dumpFile_);
190     return result;
191 }
192 
StartTone()193 bool TonePlayerImpl::StartTone()
194 {
195     std::lock_guard<std::mutex> lock(optMutex_);
196     AUDIO_INFO_LOG("STARTTONE ToneType %{public}d", toneType_);
197     CHECK_AND_RETURN_RET_LOG(toneState_ == TONE_INIT || toneState_ == TONE_STOPPED, false,
198         "Start audioRenderer_ is null");
199 
200     if (!isRendererInited_ || audioRenderer_ == nullptr) {
201         AUDIO_ERR_LOG("Start audioRenderer_ is null");
202         return false;
203     }
204     bool result = audioRenderer_->Start();
205     CHECK_AND_RETURN_RET_LOG(result, result, "Start audioRenderer_ failed");
206     toneState_ = TONE_STARTING;
207     return result;
208 }
209 
StopTone()210 bool TonePlayerImpl::StopTone()
211 {
212     std::lock_guard<std::mutex> lock(optMutex_);
213     AUDIO_INFO_LOG("STOPTONE ToneType %{public}d", toneType_);
214 
215     if (!isRendererInited_ || audioRenderer_ == nullptr) {
216         AUDIO_ERR_LOG("Stop audioRenderer_ is null");
217         return false;
218     }
219     // in plan: mark state stopping, smooth volume in onwritedata
220     bool result = audioRenderer_->Stop();
221     CHECK_AND_RETURN_RET_LOG(result, result, "Stop audioRenderer_ failed");
222     toneState_ = TONE_STOPPING;
223     return result;
224 }
225 
Release()226 bool TonePlayerImpl::Release()
227 {
228     std::unique_lock<std::mutex> lock(optMutex_);
229     toneState_ = TONE_RELEASED;
230     lock.unlock();
231     if (audioRenderer_ != nullptr) {
232         audioRenderer_->Stop();
233         audioRenderer_->Release();
234         audioRenderer_ = nullptr;
235     }
236     DumpFileUtil::CloseDumpFile(&dumpFile_);
237     return true;
238 }
239 
GetCurrentSegmentUpdated()240 void TonePlayerImpl::GetCurrentSegmentUpdated()
241 {
242     if (toneInfo_->segments[currSegment_].loopCnt) {
243         if (loopCounter_ < toneInfo_->segments[currSegment_].loopCnt) {
244             currSegment_ = toneInfo_->segments[currSegment_].loopIndx;
245             ++loopCounter_;
246         } else {
247             // completed loop. go to next segment
248             loopCounter_ = 0;
249             currSegment_++;
250         }
251     } else {
252         // no looping required , go to next segment
253         currSegment_++;
254     }
255     AUDIO_INFO_LOG("GetCurrentSegmentUpdated loopCounter_: %{public}d, currSegment_: %{public}d",
256         loopCounter_, currSegment_);
257 }
258 
CheckToneContinuity()259 bool TonePlayerImpl::CheckToneContinuity()
260 {
261     AUDIO_INFO_LOG("CheckToneContinuity Entry loopCounter_: %{public}d, currSegment_: %{public}d",
262         loopCounter_, currSegment_);
263     bool retVal = false;
264     GetCurrentSegmentUpdated();
265 
266     // Handle loop if last segment reached
267     if (toneInfo_->segments[currSegment_].duration == 0) {
268         AUDIO_DEBUG_LOG("Last Seg: %{public}d", currSegment_);
269         if (currCount_ < toneInfo_->repeatCnt) {
270             currSegment_ = toneInfo_->repeatSegment;
271             ++currCount_;
272             retVal = true;
273         } else {
274             retVal = false;
275         }
276     } else {
277         retVal = true;
278     }
279     AUDIO_DEBUG_LOG("CheckToneContinuity End loopCounter_: %{public}d, currSegment_: %{public}d currCount_: %{public}d",
280         loopCounter_, currSegment_, currCount_);
281     return retVal;
282 }
283 
ContinueToneplay(uint32_t reqSample,int8_t * audioBuffer)284 bool TonePlayerImpl::ContinueToneplay(uint32_t reqSample, int8_t *audioBuffer)
285 {
286     if (toneState_ != TONE_RUNNING) {
287         return false;
288     }
289     if (totalSample_ <= nextSegSample_) {
290         if (toneInfo_->segments[currSegment_].duration != 0) {
291             GetSamples(toneInfo_->segments[currSegment_].waveFreq, audioBuffer, reqSample);
292         }
293         return true;
294     }
295 
296     if (CheckToneContinuity()) {
297         if (toneInfo_->segments[currSegment_].duration != 0) {
298             sampleCount_ = 0;
299             GetSamples(toneInfo_->segments[currSegment_].waveFreq, audioBuffer, reqSample);
300         }
301     }
302     nextSegSample_ += (toneInfo_->segments[currSegment_].duration * samplingRate_) / C1000MS;
303     AUDIO_INFO_LOG("ContinueToneplay nextSegSample_: %{public}d", nextSegSample_);
304     return true;
305 }
306 
GetSamples(uint16_t * freqs,int8_t * buffer,uint32_t reqSamples)307 int32_t TonePlayerImpl::GetSamples(uint16_t *freqs, int8_t *buffer, uint32_t reqSamples)
308 {
309     uint32_t index;
310     uint8_t *data;
311     uint16_t freqVal;
312     float pi = 3.1428f;
313     for (uint32_t i = 0; i <= TONEINFO_MAX_WAVES; i++) {
314         if (freqs[i] == 0) {
315             break;
316         }
317         freqVal = freqs[i];
318         AUDIO_DEBUG_LOG("GetSamples Freq: %{public}d sampleCount_: %{public}d", freqVal, sampleCount_);
319         index = sampleCount_;
320         data = reinterpret_cast<uint8_t*>(buffer);
321         double factor = freqVal * 2 * pi / samplingRate_; // 2 is a parameter in the sine wave formula
322         for (uint32_t idx = 0; idx < reqSamples; idx++) {
323             int16_t sample = amplitudeType_ * sin(factor * index);
324             uint32_t result;
325             if (i == 0) {
326                 result = (sample & 0xFF);
327                 *data = result & 0xFF;
328                 data++;
329                 *data = ((sample & 0xFF00) >> BIT8);
330                 data++;
331             } else {
332                 result = *data + (static_cast<uint16_t>(sample) & 0xFF);
333                 *data = result & 0xFF;
334                 data++;
335                 *data += (result >> BIT8) + ((sample & 0xFF00) >> BIT8);
336                 data++;
337             }
338             index++;
339         }
340     }
341     sampleCount_ += reqSamples;
342     return 0;
343 }
344 
Str16ToStr8(std::u16string str)345 std::string TonePlayerImpl::Str16ToStr8(std::u16string str)
346 {
347     std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert(DEFAULT_STRING);
348     std::string result = convert.to_bytes(str);
349     return result == DEFAULT_STRING ? "" : result;
350 }
351 
GetCountryCode()352 std::string TonePlayerImpl::GetCountryCode()
353 {
354     char paramValue[SYSPARA_SIZE] = {0};
355     GetParameter(DEBUG_COUNTRYCODE_NAME, "", paramValue, SYSPARA_SIZE);
356     if (strcmp(paramValue, "")) {
357         AUDIO_DEBUG_LOG("GetParameter %{public}s", paramValue);
358         std::string countryCode(paramValue);
359         for (char &c : countryCode) {
360             c = std::tolower(c);
361         }
362         return countryCode;
363     }
364 
365     std::string countryCodeStr8 = "";
366 #if defined(AUDIO_TEL_CORE_SERVICE_ENABLE) && defined(AUIDO_TEL_CELLULAR_DATA_ENABLE)
367     int32_t slotId = Telephony::CellularDataClient::GetInstance().GetDefaultCellularDataSlotId();
368     std::u16string countryCodeForNetwork;
369     DelayedRefSingleton<Telephony::CoreServiceClient>::GetInstance().GetIsoCountryCodeForNetwork(
370         slotId, countryCodeForNetwork);
371     countryCodeStr8 = Str16ToStr8(countryCodeForNetwork);
372     if (countryCodeStr8.empty()) {
373         std::u16string countryCodeForSim;
374         DelayedRefSingleton<Telephony::CoreServiceClient>::GetInstance().GetISOCountryCodeForSim(
375             slotId, countryCodeForSim);
376         countryCodeStr8 = Str16ToStr8(countryCodeForSim);
377     }
378     AUDIO_DEBUG_LOG("GetISOCountryCode %{public}s", paramValue);
379 #endif
380     for (char &c : countryCodeStr8) {
381         c = std::tolower(c);
382     }
383     return countryCodeStr8;
384 }
385 
CheckToneStarted(uint32_t reqSample,int8_t * audioBuffer)386 bool TonePlayerImpl::CheckToneStarted(uint32_t reqSample, int8_t *audioBuffer)
387 {
388     if (toneState_ != TONE_STARTING) {
389         return false;
390     }
391     toneState_ = TONE_RUNNING;
392     if (toneInfo_->segments[currSegment_].duration != 0) {
393         sampleCount_ = 0;
394         GetSamples(toneInfo_->segments[currSegment_].waveFreq, audioBuffer, reqSample);
395     }
396     return true;
397 }
398 
CheckToneStopped()399 bool TonePlayerImpl::CheckToneStopped()
400 {
401     if (toneState_ == TONE_STOPPED) {
402         return true;
403     }
404     if (toneInfo_->segments[currSegment_].duration == 0 || totalSample_ > maxSample_ || toneState_ == TONE_STOPPING) {
405         if (toneState_ == TONE_RUNNING) {
406             toneState_ = TONE_STOPPING;
407             AUDIO_DEBUG_LOG("Audicallback move playing to stoping");
408         }
409         return true;
410     }
411     return false;
412 }
413 
AudioToneSequenceGen(BufferDesc & bufDesc)414 bool TonePlayerImpl::AudioToneSequenceGen(BufferDesc &bufDesc)
415 {
416     int8_t *audioBuffer = reinterpret_cast<int8_t *>(bufDesc.buffer);
417     uint32_t totalBufAvailable = bufDesc.bufLength / sizeof(int16_t);
418     bool retVal = true;
419     while (totalBufAvailable) {
420         uint32_t reqSamples = totalBufAvailable < processSize_ * CDOUBLE ? totalBufAvailable : processSize_;
421         AUDIO_DEBUG_LOG("AudioToneDataThreadFunc, lReqSmp: %{public}d totalBufAvailable: %{public}d",
422             reqSamples, totalBufAvailable);
423         // Update pcm frame count and end time (current time at the end of this process)
424         totalSample_ += reqSamples;
425         if (CheckToneStopped()) {
426             // in plan: do smooth works
427             AUDIO_PRERELEASE_LOGI("CheckToneStopped true toneType_ %{public}d", toneType_);
428             if (toneState_ == TONE_STOPPING) {
429                 toneState_ = TONE_STOPPED;
430                 totalBufAvailable = 0;
431             }
432             return false;
433         } else if (CheckToneStarted(reqSamples, audioBuffer)) {
434             bufDesc.dataLength += reqSamples * sizeof(int16_t);
435         } else {
436             if (ContinueToneplay(reqSamples, audioBuffer)) {
437                 bufDesc.dataLength += reqSamples * sizeof(int16_t);
438             }
439         }
440         totalBufAvailable -= reqSamples;
441         audioBuffer += reqSamples * sizeof(int16_t);
442     }
443     return retVal;
444 }
445 
InitToneWaveInfo()446 bool TonePlayerImpl::InitToneWaveInfo()
447 {
448     AUDIO_INFO_LOG("InitToneWaveInfo ToneType %{public}d", toneType_);
449     if (initialToneInfo_ == NULL) {
450         return false;
451     }
452     toneInfo_ = initialToneInfo_;
453     maxSample_ = TONEINFO_INF;
454 
455     // Initialize tone sequencer
456     totalSample_ = 0;
457     currSegment_ = 0;
458     currCount_ = 0;
459     loopCounter_ = 0;
460     if (toneInfo_->segments[0].duration == TONEINFO_INF) {
461         nextSegSample_ = TONEINFO_INF;
462     } else {
463         nextSegSample_ = (toneInfo_->segments[0].duration * samplingRate_) / C1000MS;
464     }
465     AUDIO_INFO_LOG("Prepare wave, nextSegSample_: %{public}d", nextSegSample_);
466     return true;
467 }
468 
469 
InitAudioRenderer()470 bool TonePlayerImpl::InitAudioRenderer()
471 {
472     processSize_ = (rendererOptions_.streamInfo.samplingRate * C20MS) / C1000MS;
473     audioRenderer_ = AudioRenderer::CreateRenderer(rendererOptions_);
474     CHECK_AND_RETURN_RET_LOG(audioRenderer_ != nullptr, false,
475         "Renderer create failed");
476 
477     if (rendererOptions_.rendererInfo.streamUsage == STREAM_USAGE_VOICE_MODEM_COMMUNICATION) {
478         audioRenderer_->EnableVoiceModemCommunicationStartStream(true);
479     }
480 
481     size_t targetSize = 0;
482     int32_t ret = audioRenderer_->GetBufferSize(targetSize);
483 
484     AUDIO_DEBUG_LOG("Playback renderer created");
485     int32_t setRenderMode = audioRenderer_->SetRenderMode(RENDER_MODE_CALLBACK);
486     CHECK_AND_RETURN_RET_LOG(!setRenderMode, false, "initAudioRenderer: SetRenderMode failed");
487     AUDIO_DEBUG_LOG("SetRenderMode Sucessful");
488 
489     if (ret == 0 && targetSize != 0) {
490         size_t bufferDuration = 20; // 20 -> 20ms
491         audioRenderer_->SetBufferDuration(bufferDuration);
492         AUDIO_INFO_LOG("Init renderer with buffer %{public}zu, duration %{public}zu", targetSize, bufferDuration);
493     }
494 
495     audioRenderer_->SetAudioEffectMode(EFFECT_NONE);
496 
497     int32_t setRendererWrite = audioRenderer_->SetRendererWriteCallback(shared_from_this());
498     CHECK_AND_RETURN_RET_LOG(!setRendererWrite, false, "SetRendererWriteCallback failed");
499     AUDIO_DEBUG_LOG("SetRendererWriteCallback Sucessful");
500 
501     int32_t setRendererCallback = audioRenderer_->SetRendererCallback(shared_from_this());
502     CHECK_AND_RETURN_RET_LOG(!setRendererCallback, false, "initAudioRenderer: SetRendererCallbackfailed");
503     AUDIO_DEBUG_LOG("SetRendererCallback Sucessful");
504     return true;
505 }
506 } // end namespace AudioStandard
507 } // end OHOS
508