1 /*
2  * Copyright (C) 2021 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 "tone.h"
17 
18 #include <thread>
19 
20 #include "telephony_log_wrapper.h"
21 
22 namespace OHOS {
23 namespace Telephony {
24 using AudioPlay = int32_t (AudioPlayer::*)(const std::string &, AudioStandard::AudioStreamType, PlayerType);
25 
Tone()26 Tone::Tone() : audioPlayer_(new (std::nothrow) AudioPlayer()) {}
27 
Tone(ToneDescriptor tone)28 Tone::Tone(ToneDescriptor tone) : audioPlayer_(new (std::nothrow) AudioPlayer())
29 {
30     currentToneDescriptor_ = tone;
31 }
32 
~Tone()33 Tone::~Tone()
34 {
35     if (audioPlayer_ != nullptr) {
36         delete audioPlayer_;
37         audioPlayer_ = nullptr;
38     }
39 }
40 
Init()41 void Tone::Init() {}
42 
Play()43 int32_t Tone::Play()
44 {
45     if (currentToneDescriptor_ == TONE_UNKNOWN) {
46         TELEPHONY_LOGE("tone descriptor unknown");
47         return CALL_ERR_AUDIO_UNKNOWN_TONE;
48     }
49     if (IsUseTonePlayer(currentToneDescriptor_)) {
50         TELEPHONY_LOGI("currentToneDescriptor = %{public}d", currentToneDescriptor_);
51         if (!InitTonePlayer()) {
52             TELEPHONY_LOGE("InitTonePlayer failed");
53             return TELEPHONY_ERROR;
54         }
55         if (currentToneDescriptor_ == ToneDescriptor::TONE_FINISHED) {
56             if (!tonePlayer_->StartTone()) {
57                 return CALL_ERR_AUDIO_TONE_PLAY_FAILED;
58             }
59             return TELEPHONY_SUCCESS;
60         }
61         std::thread play([&]() {
62             pthread_setname_np(pthread_self(), TONE_PLAY_THREAD);
63             tonePlayer_->StartTone();
64         });
65         play.detach();
66     } else {
67         AudioPlay audioPlay = &AudioPlayer::Play;
68         if (audioPlayer_ == nullptr) {
69             TELEPHONY_LOGE("audioPlayer_ is nullptr");
70             return TELEPHONY_ERR_LOCAL_PTR_NULL;
71         }
72         std::thread play(audioPlay, audioPlayer_, GetToneDescriptorPath(currentToneDescriptor_),
73             AudioStandard::AudioStreamType::STREAM_MUSIC, PlayerType::TYPE_TONE);
74         pthread_setname_np(play.native_handle(), TONE_PLAY_THREAD);
75         play.detach();
76     }
77     return TELEPHONY_SUCCESS;
78 }
79 
Stop()80 int32_t Tone::Stop()
81 {
82     std::lock_guard<std::mutex> lock(mutex_);
83     if (currentToneDescriptor_ == TONE_UNKNOWN) {
84         TELEPHONY_LOGE("tone descriptor unknown");
85         return CALL_ERR_AUDIO_UNKNOWN_TONE;
86     }
87     if (IsUseTonePlayer(currentToneDescriptor_)) {
88         if (tonePlayer_ != nullptr) {
89             tonePlayer_->StopTone();
90             tonePlayer_->Release();
91         }
92     } else {
93         if (audioPlayer_ == nullptr) {
94             TELEPHONY_LOGE("audioPlayer_ is nullptr");
95             return TELEPHONY_ERR_LOCAL_PTR_NULL;
96         }
97         audioPlayer_->SetStop(PlayerType::TYPE_TONE, true);
98     }
99     return TELEPHONY_SUCCESS;
100 }
101 
InitTonePlayer()102 bool Tone::InitTonePlayer()
103 {
104     using namespace OHOS::AudioStandard;
105     if (tonePlayer_ == nullptr) {
106         StreamUsage streamUsage = GetStreamUsageByToneType(currentToneDescriptor_);
107         AudioRendererInfo rendererInfo = {};
108         rendererInfo.contentType = ContentType::CONTENT_TYPE_UNKNOWN;
109         rendererInfo.streamUsage = streamUsage;
110         rendererInfo.rendererFlags = 0;
111         tonePlayer_ = TonePlayer::Create(rendererInfo);
112         if (tonePlayer_ == nullptr) {
113             return false;
114         }
115         ToneType toneType = ConvertToneDescriptorToToneType(currentToneDescriptor_);
116         if (!tonePlayer_->LoadTone(toneType)) {
117             return false;
118         }
119     }
120     return true;
121 }
122 
ConvertDigitToTone(char digit)123 ToneDescriptor Tone::ConvertDigitToTone(char digit)
124 {
125     ToneDescriptor dtmf = ToneDescriptor::TONE_UNKNOWN;
126     switch (digit) {
127         case '0':
128             dtmf = ToneDescriptor::TONE_DTMF_CHAR_0;
129             break;
130         case '1':
131             dtmf = ToneDescriptor::TONE_DTMF_CHAR_1;
132             break;
133         case '2':
134             dtmf = ToneDescriptor::TONE_DTMF_CHAR_2;
135             break;
136         case '3':
137             dtmf = ToneDescriptor::TONE_DTMF_CHAR_3;
138             break;
139         case '4':
140             dtmf = ToneDescriptor::TONE_DTMF_CHAR_4;
141             break;
142         case '5':
143             dtmf = ToneDescriptor::TONE_DTMF_CHAR_5;
144             break;
145         case '6':
146             dtmf = ToneDescriptor::TONE_DTMF_CHAR_6;
147             break;
148         case '7':
149             dtmf = ToneDescriptor::TONE_DTMF_CHAR_7;
150             break;
151         case '8':
152             dtmf = ToneDescriptor::TONE_DTMF_CHAR_8;
153             break;
154         case '9':
155             dtmf = ToneDescriptor::TONE_DTMF_CHAR_9;
156             break;
157         case '*':
158             dtmf = ToneDescriptor::TONE_DTMF_CHAR_P;
159             break;
160         case '#':
161             dtmf = ToneDescriptor::TONE_DTMF_CHAR_W;
162             break;
163         default:
164             break;
165     }
166     return dtmf;
167 }
168 
ConvertToneDescriptorToToneType(ToneDescriptor tone)169 AudioStandard::ToneType Tone::ConvertToneDescriptorToToneType(ToneDescriptor tone)
170 {
171     using namespace OHOS::AudioStandard;
172     ToneType tonType = ToneType::NUM_TONES;
173     switch (tone) {
174         case ToneDescriptor::TONE_DTMF_CHAR_0:
175             tonType = ToneType::TONE_TYPE_DIAL_0;
176             break;
177         case ToneDescriptor::TONE_DTMF_CHAR_1:
178             tonType = ToneType::TONE_TYPE_DIAL_1;
179             break;
180         case ToneDescriptor::TONE_DTMF_CHAR_2:
181             tonType = ToneType::TONE_TYPE_DIAL_2;
182             break;
183         case ToneDescriptor::TONE_DTMF_CHAR_3:
184             tonType = ToneType::TONE_TYPE_DIAL_3;
185             break;
186         case ToneDescriptor::TONE_DTMF_CHAR_4:
187             tonType = ToneType::TONE_TYPE_DIAL_4;
188             break;
189         case ToneDescriptor::TONE_DTMF_CHAR_5:
190             tonType = ToneType::TONE_TYPE_DIAL_5;
191             break;
192         case ToneDescriptor::TONE_DTMF_CHAR_6:
193             tonType = ToneType::TONE_TYPE_DIAL_6;
194             break;
195         case ToneDescriptor::TONE_DTMF_CHAR_7:
196             tonType = ToneType::TONE_TYPE_DIAL_7;
197             break;
198         case ToneDescriptor::TONE_DTMF_CHAR_8:
199             tonType = ToneType::TONE_TYPE_DIAL_8;
200             break;
201         case ToneDescriptor::TONE_DTMF_CHAR_9:
202             tonType = ToneType::TONE_TYPE_DIAL_9;
203             break;
204         case ToneDescriptor::TONE_DTMF_CHAR_P:
205             tonType = ToneType::TONE_TYPE_DIAL_S;
206             break;
207         case ToneDescriptor::TONE_DTMF_CHAR_W:
208             tonType = ToneType::TONE_TYPE_DIAL_P;
209             break;
210         default:
211             tonType = ConvertCallToneDescriptorToToneType(tone);
212             break;
213     }
214     return tonType;
215 }
216 
ConvertCallToneDescriptorToToneType(ToneDescriptor tone)217 AudioStandard::ToneType Tone::ConvertCallToneDescriptorToToneType(ToneDescriptor tone)
218 {
219     using namespace OHOS::AudioStandard;
220     ToneType tonType = ToneType::NUM_TONES;
221     switch (tone) {
222         case ToneDescriptor::TONE_RINGBACK:
223             tonType = ToneType::TONE_TYPE_COMMON_SUPERVISORY_RINGTONE;
224             break;
225         case ToneDescriptor::TONE_WAITING:
226             tonType = ToneType::TONE_TYPE_COMMON_SUPERVISORY_CALL_WAITING;
227             break;
228         case ToneDescriptor::TONE_FINISHED:
229             tonType = ToneType::TONE_TYPE_COMMON_PROPRIETARY_PROMPT;
230             break;
231         default:
232             break;
233     }
234     return tonType;
235 }
236 
GetStreamUsageByToneType(ToneDescriptor descriptor)237 AudioStandard::StreamUsage Tone::GetStreamUsageByToneType(ToneDescriptor descriptor)
238 {
239     AudioStandard::StreamUsage streamUsage = AudioStandard::StreamUsage::STREAM_USAGE_UNKNOWN;
240     switch (descriptor) {
241         case ToneDescriptor::TONE_DTMF_CHAR_0:
242         case ToneDescriptor::TONE_DTMF_CHAR_1:
243         case ToneDescriptor::TONE_DTMF_CHAR_2:
244         case ToneDescriptor::TONE_DTMF_CHAR_3:
245         case ToneDescriptor::TONE_DTMF_CHAR_4:
246         case ToneDescriptor::TONE_DTMF_CHAR_5:
247         case ToneDescriptor::TONE_DTMF_CHAR_6:
248         case ToneDescriptor::TONE_DTMF_CHAR_7:
249         case ToneDescriptor::TONE_DTMF_CHAR_8:
250         case ToneDescriptor::TONE_DTMF_CHAR_9:
251         case ToneDescriptor::TONE_DTMF_CHAR_P:
252         case ToneDescriptor::TONE_DTMF_CHAR_W:
253             streamUsage = AudioStandard::StreamUsage::STREAM_USAGE_DTMF;
254             break;
255         case ToneDescriptor::TONE_RINGBACK:
256             streamUsage = AudioStandard::StreamUsage::STREAM_USAGE_VOICE_MODEM_COMMUNICATION;
257             break;
258         case ToneDescriptor::TONE_WAITING:
259         case ToneDescriptor::TONE_FINISHED:
260             streamUsage = AudioStandard::StreamUsage::STREAM_USAGE_VOICE_RINGTONE;
261             break;
262         default:
263             break;
264     }
265     return streamUsage;
266 }
267 
IsUseTonePlayer(ToneDescriptor tone)268 bool Tone::IsUseTonePlayer(ToneDescriptor tone)
269 {
270     bool ret = false;
271     switch (tone) {
272         case ToneDescriptor::TONE_DTMF_CHAR_0:
273         case ToneDescriptor::TONE_DTMF_CHAR_1:
274         case ToneDescriptor::TONE_DTMF_CHAR_2:
275         case ToneDescriptor::TONE_DTMF_CHAR_3:
276         case ToneDescriptor::TONE_DTMF_CHAR_4:
277         case ToneDescriptor::TONE_DTMF_CHAR_5:
278         case ToneDescriptor::TONE_DTMF_CHAR_6:
279         case ToneDescriptor::TONE_DTMF_CHAR_7:
280         case ToneDescriptor::TONE_DTMF_CHAR_8:
281         case ToneDescriptor::TONE_DTMF_CHAR_9:
282         case ToneDescriptor::TONE_DTMF_CHAR_P:
283         case ToneDescriptor::TONE_DTMF_CHAR_W:
284             ret = true;
285             break;
286         case ToneDescriptor::TONE_RINGBACK:
287         case ToneDescriptor::TONE_WAITING:
288         case ToneDescriptor::TONE_FINISHED:
289             ret = true;
290             break;
291         default:
292             break;
293     }
294     return ret;
295 }
296 
GetToneDescriptorPath(ToneDescriptor tone)297 std::string Tone::GetToneDescriptorPath(ToneDescriptor tone)
298 {
299 #ifdef ABILITY_AUDIO_SUPPORT
300     return DelayedSingleton<AudioProxy>::GetInstance()->GetToneDescriptorPath(tone);
301 #endif
302     return DelayedSingleton<AudioProxy>::GetInstance()->GetDefaultTonePath();
303 }
304 
ReleaseRenderer()305 void Tone::ReleaseRenderer()
306 {
307     if (audioPlayer_ == nullptr) {
308         TELEPHONY_LOGE("audioPlayer_ is nullptr");
309         return;
310     }
311     audioPlayer_->ReleaseRenderer();
312 }
313 
getCurrentToneType()314 ToneDescriptor Tone::getCurrentToneType()
315 {
316     return currentToneDescriptor_;
317 }
318 } // namespace Telephony
319 } // namespace OHOS
320