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 "ringtone_player_impl.h"
17
18 #include <sys/stat.h>
19
20 #include "media_log.h"
21 #include "media_errors.h"
22
23 using namespace std;
24 using namespace OHOS::AbilityRuntime;
25
26 namespace {
27 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_AUDIO_NAPI, "RingtonePlayer"};
28 }
29
30 namespace OHOS {
31 namespace Media {
32 const float HIGH_VOL = 1.0f;
33 const float LOW_VOL = 0.0f;
34 const std::string AUDIO_FORMAT_STR = ".ogg";
35 const std::string HAPTIC_FORMAT_STR = ".json";
36
RingtonePlayerImpl(const shared_ptr<Context> & context,SystemSoundManagerImpl & sysSoundMgr,RingtoneType type)37 RingtonePlayerImpl::RingtonePlayerImpl(const shared_ptr<Context> &context,
38 SystemSoundManagerImpl &sysSoundMgr, RingtoneType type)
39 : volume_(HIGH_VOL),
40 loop_(false),
41 context_(context),
42 systemSoundMgr_(sysSoundMgr),
43 type_(type)
44 {
45 audioHapticManager_ = AudioHapticManagerFactory::CreateAudioHapticManager();
46 CHECK_AND_RETURN_LOG(audioHapticManager_ != nullptr, "Failed to get audio haptic manager");
47
48 std::string ringtoneUri = systemSoundMgr_.GetRingtoneUri(context_, type_);
49 InitPlayer(ringtoneUri);
50 }
51
~RingtonePlayerImpl()52 RingtonePlayerImpl::~RingtonePlayerImpl()
53 {
54 if (player_ != nullptr) {
55 player_->Release();
56 (void)SystemSoundVibrator::StopVibrator();
57 player_ = nullptr;
58 callback_ = nullptr;
59 }
60 if (audioHapticManager_ != nullptr) {
61 audioHapticManager_->UnregisterSource(sourceId_);
62 audioHapticManager_ = nullptr;
63 }
64 }
65
IsFileExisting(const std::string & fileUri)66 bool RingtonePlayerImpl::IsFileExisting(const std::string &fileUri)
67 {
68 struct stat buffer;
69 return (stat(fileUri.c_str(), &buffer) == 0);
70 }
71
GetHapticUriForAudioUri(const std::string & audioUri)72 std::string RingtonePlayerImpl::GetHapticUriForAudioUri(const std::string &audioUri)
73 {
74 std::string hapticUri = "";
75 if (audioUri.length() > AUDIO_FORMAT_STR.length() &&
76 audioUri.rfind(AUDIO_FORMAT_STR) == audioUri.length() - AUDIO_FORMAT_STR.length()) {
77 // the end of audio uri is ".ogg"
78 hapticUri = audioUri;
79 hapticUri.replace(hapticUri.rfind(AUDIO_FORMAT_STR), AUDIO_FORMAT_STR.length(), HAPTIC_FORMAT_STR);
80 }
81
82 if (hapticUri == "" || !IsFileExisting(hapticUri)) {
83 MEDIA_LOGW("Failed to find the vibration json file for audioUri. Use the default json file.");
84 std::string defaultRingtoneUri = systemSoundMgr_.GetDefaultRingtoneUri(RINGTONE_TYPE_SIM_CARD_0);
85 if (defaultRingtoneUri.length() > AUDIO_FORMAT_STR.length() &&
86 defaultRingtoneUri.rfind(AUDIO_FORMAT_STR) == defaultRingtoneUri.length() - AUDIO_FORMAT_STR.length()) {
87 // the end of default ringtone uri is ".ogg"
88 hapticUri = defaultRingtoneUri;
89 hapticUri.replace(hapticUri.rfind(AUDIO_FORMAT_STR), AUDIO_FORMAT_STR.length(), HAPTIC_FORMAT_STR);
90 } else {
91 MEDIA_LOGW("The default ringtone uri is invalid!");
92 }
93 }
94
95 return hapticUri;
96 }
97
CreateDataShareHelper(int32_t systemAbilityId)98 static shared_ptr<DataShare::DataShareHelper> CreateDataShareHelper(int32_t systemAbilityId)
99 {
100 auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
101 if (saManager == nullptr) {
102 return nullptr;
103 }
104 auto remoteObj = saManager->GetSystemAbility(systemAbilityId);
105 if (remoteObj == nullptr) {
106 return nullptr;
107 }
108 return DataShare::DataShareHelper::Creator(remoteObj, RINGTONE_URI);
109 }
110
ChangeUri(const std::string & audioUri)111 std::string RingtonePlayerImpl::ChangeUri(const std::string &audioUri)
112 {
113 const std::string FDHEAD = "fd://";
114 std::string ringtoneUri = audioUri;
115 size_t found = audioUri.find(RINGTONE_CUSTOMIZED_BASE_PATH);
116 if (found != std::string::npos) {
117 std::shared_ptr<DataShare::DataShareHelper> dataShareHelper =
118 CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID);
119 CHECK_AND_RETURN_RET_LOG(dataShareHelper != nullptr, audioUri, "Failed to create dataShareHelper.");
120 DataShare::DatashareBusinessError businessError;
121 DataShare::DataSharePredicates queryPredicates;
122 Uri ringtonePathUri(RINGTONE_PATH_URI);
123 vector<string> columns = {{RINGTONE_COLUMN_TONE_ID}, {RINGTONE_COLUMN_DATA}};
124 queryPredicates.EqualTo(RINGTONE_COLUMN_DATA, audioUri);
125 auto resultSet = dataShareHelper->Query(ringtonePathUri, queryPredicates, columns, &businessError);
126 auto results = make_unique<RingtoneFetchResult<RingtoneAsset>>(move(resultSet));
127 unique_ptr<RingtoneAsset> ringtoneAsset = results->GetFirstObject();
128 if (ringtoneAsset != nullptr) {
129 string uriStr = RINGTONE_PATH_URI + RINGTONE_SLASH_CHAR + to_string(ringtoneAsset->GetId());
130 Uri ofUri(uriStr);
131 int32_t fd = dataShareHelper->OpenFile(ofUri, "r");
132 if (fd > 0) {
133 ringtoneUri = FDHEAD + to_string(fd);
134 }
135 }
136 resultSet == nullptr ? : resultSet->Close();
137 dataShareHelper->Release();
138 }
139 MEDIA_LOGI("RingtonePlayerImpl::ChangeUri ringtoneUri is %{public}s", ringtoneUri.c_str());
140 return ringtoneUri;
141 }
142
InitPlayer(std::string & audioUri)143 void RingtonePlayerImpl::InitPlayer(std::string &audioUri)
144 {
145 if (sourceId_ != -1) {
146 (void)audioHapticManager_->UnregisterSource(sourceId_);
147 sourceId_ = -1;
148 }
149
150 AudioHapticPlayerOptions options = {false, false};
151 // Get the haptic file uri according to the audio file uri.
152 std::string hapticUri = GetHapticUriForAudioUri(audioUri);
153 if (hapticUri == "") {
154 MEDIA_LOGW("haptic uri is empty. Play ringtone without vibration");
155 options.muteHaptics = true;
156 }
157
158 sourceId_ = audioHapticManager_->RegisterSource(ChangeUri(audioUri), hapticUri);
159 CHECK_AND_RETURN_LOG(sourceId_ != -1, "Failed to register source for audio haptic manager");
160 (void)audioHapticManager_->SetAudioLatencyMode(sourceId_, AUDIO_LATENCY_MODE_NORMAL);
161 (void)audioHapticManager_->SetStreamUsage(sourceId_, AudioStandard::StreamUsage::STREAM_USAGE_VOICE_RINGTONE);
162
163 if (systemSoundMgr_.GetRingerMode() == AudioStandard::AudioRingerMode::RINGER_MODE_SILENT) {
164 options.muteHaptics = true;
165 }
166 player_ = audioHapticManager_->CreatePlayer(sourceId_, options);
167 CHECK_AND_RETURN_LOG(player_ != nullptr, "Failed to create ringtone player instance");
168 int32_t result = player_->Prepare();
169 CHECK_AND_RETURN_LOG(result == MSERR_OK, "Failed to load source for audio haptic manager");
170 configuredUri_ = audioUri;
171
172 if (callback_ == nullptr) {
173 callback_ = std::make_shared<RingtonePlayerCallback>(*this);
174 }
175 CHECK_AND_RETURN_LOG(callback_ != nullptr, "Failed to create callback object");
176 (void)player_->SetAudioHapticPlayerCallback(callback_);
177 (void)player_->SetVolume(volume_);
178 (void)player_->SetLoop(loop_);
179
180 ringtoneState_ = STATE_NEW;
181 }
182
Configure(const float & volume,const bool & loop)183 int32_t RingtonePlayerImpl::Configure(const float &volume, const bool &loop)
184 {
185 MEDIA_LOGI("RingtonePlayerImpl::Configure with volume %{public}f, loop %{public}d", volume, loop);
186 CHECK_AND_RETURN_RET_LOG(volume >= LOW_VOL && volume <= HIGH_VOL,
187 MSERR_INVALID_VAL, "Volume level invalid");
188
189 std::lock_guard<std::mutex> lock(playerMutex_);
190 CHECK_AND_RETURN_RET_LOG(player_ != nullptr && ringtoneState_ != STATE_INVALID, MSERR_INVALID_VAL, "no player_");
191 volume_ = volume;
192 loop_ = loop;
193 (void)player_->SetVolume(volume_);
194 (void)player_->SetLoop(loop_);
195
196 return MSERR_OK;
197 }
198
Start()199 int32_t RingtonePlayerImpl::Start()
200 {
201 MEDIA_LOGI("RingtonePlayerImpl::Start");
202 std::lock_guard<std::mutex> lock(playerMutex_);
203 CHECK_AND_RETURN_RET_LOG(ringtoneState_ != STATE_RUNNING, MSERR_INVALID_OPERATION, "ringtone player is running");
204 CHECK_AND_RETURN_RET_LOG(player_ != nullptr && ringtoneState_ != STATE_INVALID, MSERR_INVALID_VAL, "no player_");
205
206 std::string ringtoneUri = systemSoundMgr_.GetRingtoneUri(context_, type_);
207 if (ringtoneUri != configuredUri_) {
208 MEDIA_LOGI("Ringtone uri changed. Reload player");
209 InitPlayer(ringtoneUri);
210 }
211 int32_t ret = player_->Start();
212 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_START_FAILED, "Start failed %{public}d", ret);
213 ringtoneState_ = STATE_RUNNING;
214
215 return MSERR_OK;
216 }
217
Stop()218 int32_t RingtonePlayerImpl::Stop()
219 {
220 MEDIA_LOGI("RingtonePlayerImpl::Stop");
221 std::lock_guard<std::mutex> lock(playerMutex_);
222 CHECK_AND_RETURN_RET_LOG(ringtoneState_ != STATE_STOPPED, MSERR_INVALID_OPERATION,
223 "ringtone player has been stopped");
224 CHECK_AND_RETURN_RET_LOG(player_ != nullptr && ringtoneState_ != STATE_INVALID, MSERR_INVALID_VAL, "no player_");
225
226 (void)player_->Stop();
227 ringtoneState_ = STATE_STOPPED;
228
229 return MSERR_OK;
230 }
231
Release()232 int32_t RingtonePlayerImpl::Release()
233 {
234 MEDIA_LOGI("RingtonePlayerImpl::Release");
235 std::lock_guard<std::mutex> lock(playerMutex_);
236 CHECK_AND_RETURN_RET_LOG(ringtoneState_ != STATE_RELEASED, MSERR_INVALID_OPERATION,
237 "ringtone player has been released");
238 CHECK_AND_RETURN_RET_LOG(player_ != nullptr && ringtoneState_ != STATE_INVALID, MSERR_INVALID_VAL, "no player_");
239
240 (void)player_->Release();
241 player_ = nullptr;
242 callback_ = nullptr;
243
244 if (audioHapticManager_ != nullptr) {
245 audioHapticManager_->UnregisterSource(sourceId_);
246 audioHapticManager_ = nullptr;
247 }
248 sourceId_ = -1;
249 configuredUri_ = "";
250
251 ringtoneState_ = STATE_RELEASED;
252 return MSERR_OK;
253 }
254
GetRingtoneState()255 RingtoneState RingtonePlayerImpl::GetRingtoneState()
256 {
257 MEDIA_LOGI("RingtonePlayerImpl::GetRingtoneState");
258 std::lock_guard<std::mutex> lock(playerMutex_);
259 return ringtoneState_;
260 }
261
GetAudioRendererInfo(AudioStandard::AudioRendererInfo & rendererInfo) const262 int32_t RingtonePlayerImpl::GetAudioRendererInfo(AudioStandard::AudioRendererInfo &rendererInfo) const
263 {
264 MEDIA_LOGI("RingtonePlayerImpl::GetAudioRendererInfo");
265 rendererInfo.contentType = AudioStandard::ContentType::CONTENT_TYPE_UNKNOWN;
266 rendererInfo.streamUsage = AudioStandard::StreamUsage::STREAM_USAGE_RINGTONE;
267 rendererInfo.rendererFlags = 0;
268 return MSERR_OK;
269 }
270
GetTitle()271 std::string RingtonePlayerImpl::GetTitle()
272 {
273 MEDIA_LOGI("RingtonePlayerImpl::GetTitle");
274 CHECK_AND_RETURN_RET_LOG(configuredUri_ != "", "", "Configured uri is null");
275 return systemSoundMgr_.GetRingtoneTitle(configuredUri_);
276 }
277
SetRingtonePlayerInterruptCallback(const std::shared_ptr<RingtonePlayerInterruptCallback> & interruptCallback)278 int32_t RingtonePlayerImpl::SetRingtonePlayerInterruptCallback(
279 const std::shared_ptr<RingtonePlayerInterruptCallback> &interruptCallback)
280 {
281 MEDIA_LOGI("RingtonePlayerImpl::SetRingtonePlayerInterruptCallback");
282 std::lock_guard<std::mutex> lock(playerMutex_);
283 interruptCallback_ = interruptCallback;
284 return MSERR_OK;
285 }
286
NotifyEndofStreamEvent()287 void RingtonePlayerImpl::NotifyEndofStreamEvent()
288 {
289 std::lock_guard<std::mutex> lock(playerMutex_);
290 ringtoneState_ = RingtoneState::STATE_STOPPED;
291 }
292
NotifyInterruptEvent(const AudioStandard::InterruptEvent & interruptEvent)293 void RingtonePlayerImpl::NotifyInterruptEvent(const AudioStandard::InterruptEvent &interruptEvent)
294 {
295 if (interruptCallback_ != nullptr) {
296 interruptCallback_->OnInterrupt(interruptEvent);
297 MEDIA_LOGI("RingtonePlayerImpl::NotifyInterruptEvent");
298 } else {
299 MEDIA_LOGE("RingtonePlayerImpl::interruptCallback_ is nullptr");
300 }
301 }
302
303 // Callback class symbols
RingtonePlayerCallback(RingtonePlayerImpl & ringtonePlayerImpl)304 RingtonePlayerCallback::RingtonePlayerCallback(RingtonePlayerImpl &ringtonePlayerImpl)
305 : ringtonePlayerImpl_(ringtonePlayerImpl) {}
306
OnInterrupt(const AudioStandard::InterruptEvent & interruptEvent)307 void RingtonePlayerCallback::OnInterrupt(const AudioStandard::InterruptEvent &interruptEvent)
308 {
309 MEDIA_LOGI("RingtonePlayerCallback::OnInterrupt: hintTye %{public}d", interruptEvent.hintType);
310 ringtonePlayerImpl_.NotifyInterruptEvent(interruptEvent);
311 }
312
OnEndOfStream(void)313 void RingtonePlayerCallback::OnEndOfStream(void)
314 {
315 MEDIA_LOGI("RingtonePlayerCallback::OnEndOfStream");
316 ringtonePlayerImpl_.NotifyEndofStreamEvent();
317 }
318
OnError(int32_t errorCode)319 void RingtonePlayerCallback::OnError(int32_t errorCode)
320 {
321 MEDIA_LOGI("OnError from audio haptic player. errorCode %{public}d", errorCode);
322 }
323 } // namesapce AudioStandard
324 } // namespace OHOS
325