1 /*
2 * Copyright (c) 2021-2022 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_ringtone_manager.h"
17
18 using namespace std;
19 using namespace OHOS::AbilityRuntime;
20 using namespace OHOS::NativeRdb;
21 using namespace OHOS::Media;
22
23 namespace OHOS {
24 namespace AudioStandard {
CreateRingtoneManager()25 unique_ptr<IRingtoneSoundManager> RingtoneFactory::CreateRingtoneManager()
26 {
27 unique_ptr<RingtoneSoundManager> soundMgr = make_unique<RingtoneSoundManager>();
28 CHECK_AND_RETURN_RET_LOG(soundMgr != nullptr, nullptr, "Failed to create sound manager object");
29
30 return soundMgr;
31 }
32
~RingtoneSoundManager()33 RingtoneSoundManager::~RingtoneSoundManager()
34 {
35 if (abilityHelper_ != nullptr) {
36 abilityHelper_->Release();
37 abilityHelper_ = nullptr;
38 }
39 }
40
SetSystemRingtoneUri(const shared_ptr<Context> & context,const string & uri,RingtoneType type)41 int32_t RingtoneSoundManager::SetSystemRingtoneUri(const shared_ptr<Context> &context, const string &uri,
42 RingtoneType type)
43 {
44 MEDIA_INFO_LOG("RingtoneSoundManager::%{public}s", __func__);
45 CHECK_AND_RETURN_RET_LOG(type >= RINGTONE_TYPE_DEFAULT && type <= RINGTONE_TYPE_MULTISIM,
46 ERR_INVALID_PARAM, "invalid type");
47
48 ValuesBucket valuesBucket;
49 valuesBucket.PutString(MEDIA_DATA_DB_RINGTONE_URI, uri);
50 valuesBucket.PutInt(MEDIA_DATA_DB_RINGTONE_TYPE, type);
51
52 return SetUri(context, valuesBucket, kvstoreOperation[SET_URI_INDEX][RINGTONE_INDEX]);
53 }
54
SetSystemNotificationUri(const shared_ptr<Context> & context,const string & uri)55 int32_t RingtoneSoundManager::SetSystemNotificationUri(const shared_ptr<Context> &context, const string &uri)
56 {
57 MEDIA_INFO_LOG("RingtoneSoundManager::%{public}s", __func__);
58
59 ValuesBucket valuesBucket;
60 valuesBucket.PutString(MEDIA_DATA_DB_NOTIFICATION_URI, uri);
61
62 return SetUri(context, valuesBucket, kvstoreOperation[SET_URI_INDEX][NOTIFICATION_INDEX]);
63 }
64
SetSystemAlarmUri(const shared_ptr<Context> & context,const string & uri)65 int32_t RingtoneSoundManager::SetSystemAlarmUri(const shared_ptr<Context> &context, const string &uri)
66 {
67 MEDIA_INFO_LOG("RingtoneSoundManager::%{public}s", __func__);
68
69 ValuesBucket valuesBucket;
70 valuesBucket.PutString(MEDIA_DATA_DB_ALARM_URI, uri);
71
72 return SetUri(context, valuesBucket, kvstoreOperation[SET_URI_INDEX][ALARM_INDEX]);
73 }
74
GetSystemRingtoneUri(const shared_ptr<Context> & context,RingtoneType type)75 string RingtoneSoundManager::GetSystemRingtoneUri(const shared_ptr<Context> &context, RingtoneType type)
76 {
77 MEDIA_INFO_LOG("RingtoneSoundManager::%{public}s", __func__);
78 CHECK_AND_RETURN_RET_LOG(type >= RINGTONE_TYPE_DEFAULT && type <= RINGTONE_TYPE_MULTISIM, "", "invalid type");
79
80 return FetchUri(context, kvstoreOperation[GET_URI_INDEX][RINGTONE_INDEX] + "/" + to_string(type));
81 }
82
GetSystemNotificationUri(const shared_ptr<Context> & context)83 string RingtoneSoundManager::GetSystemNotificationUri(const shared_ptr<Context> &context)
84 {
85 MEDIA_INFO_LOG("RingtoneSoundManager::%{public}s", __func__);
86
87 return FetchUri(context, kvstoreOperation[GET_URI_INDEX][NOTIFICATION_INDEX]);
88 }
89
GetSystemAlarmUri(const shared_ptr<Context> & context)90 string RingtoneSoundManager::GetSystemAlarmUri(const shared_ptr<Context> &context)
91 {
92 MEDIA_INFO_LOG("RingtoneSoundManager::%{public}s", __func__);
93
94 return FetchUri(context, kvstoreOperation[GET_URI_INDEX][ALARM_INDEX]);
95 }
96
SetUri(const shared_ptr<Context> & context,const ValuesBucket & valueBucket,const std::string & operation)97 int32_t RingtoneSoundManager::SetUri(const shared_ptr<Context> &context, const ValuesBucket &valueBucket,
98 const std::string &operation)
99 {
100 MEDIA_INFO_LOG("RingtoneSoundManager::%{public}s, operation is %{public}s", __func__, operation.c_str());
101
102 CreateDataAbilityHelper(context);
103 CHECK_AND_RETURN_RET_LOG(abilityHelper_ != nullptr, ERR_INVALID_PARAM, "Helper is null, failed to set uri");
104
105 Uri uri(Media::MEDIALIBRARY_DATA_URI + "/" + MEDIA_KVSTOREOPRN + "/" + operation);
106
107 int32_t result = 0;
108 result = abilityHelper_->Insert(uri, valueBucket);
109 if (result != SUCCESS) {
110 MEDIA_ERR_LOG("RingtoneSoundManager::insert ringtone uri failed");
111 }
112
113 return result;
114 }
115
FetchUri(const shared_ptr<Context> & context,const std::string & operation)116 string RingtoneSoundManager::FetchUri(const shared_ptr<Context> &context, const std::string &operation)
117 {
118 MEDIA_INFO_LOG("RingtoneSoundManager::%{public}s, operation is %{public}s", __func__, operation.c_str());
119
120 CreateDataAbilityHelper(context);
121 CHECK_AND_RETURN_RET_LOG(abilityHelper_ != nullptr, "", "Helper is null, failed to retrieve uri");
122
123 Uri uri(Media::MEDIALIBRARY_DATA_URI + "/" + MEDIA_KVSTOREOPRN + "/" + operation);
124
125 return abilityHelper_->GetType(uri);
126 }
127
CreateDataAbilityHelper(const shared_ptr<Context> & context)128 void RingtoneSoundManager::CreateDataAbilityHelper(const shared_ptr<Context> &context)
129 {
130 if (abilityHelper_ == nullptr) {
131 auto contextUri = make_unique<Uri>(Media::MEDIALIBRARY_DATA_URI);
132 CHECK_AND_RETURN_LOG(contextUri != nullptr, "failed to create context uri");
133
134 abilityHelper_ = AppExecFwk::DataAbilityHelper::Creator(context, move(contextUri));
135 CHECK_AND_RETURN_LOG(abilityHelper_ != nullptr, "Unable to create data ability helper");
136 }
137 }
138
GetRingtonePlayer(const shared_ptr<Context> & context,RingtoneType type)139 shared_ptr<IRingtonePlayer> RingtoneSoundManager::GetRingtonePlayer(const shared_ptr<Context> &context,
140 RingtoneType type)
141 {
142 MEDIA_INFO_LOG("RingtoneSoundManager::%{public}s, type %{public}d", __func__, type);
143 CHECK_AND_RETURN_RET_LOG(type >= RINGTONE_TYPE_DEFAULT && type <= RINGTONE_TYPE_MULTISIM, nullptr, "invalid type");
144
145 if (ringtonePlayer_[type] != nullptr && ringtonePlayer_[type]->GetRingtoneState() == STATE_RELEASED) {
146 ringtonePlayer_[type] = nullptr;
147 }
148
149 if (ringtonePlayer_[type] == nullptr) {
150 ringtonePlayer_[type] = make_shared<RingtonePlayer>(context, *this, type);
151 CHECK_AND_RETURN_RET_LOG(ringtonePlayer_[type] != nullptr, nullptr, "Failed to create ringtone player object");
152 }
153
154 return ringtonePlayer_[type];
155 }
156
157 // Player class symbols
RingtonePlayer(const shared_ptr<Context> & context,RingtoneSoundManager & audioMgr,RingtoneType type)158 RingtonePlayer::RingtonePlayer(const shared_ptr<Context> &context, RingtoneSoundManager &audioMgr, RingtoneType type)
159 : volume_(HIGH_VOL), loop_(false), context_(context), audioRingtoneMgr_(audioMgr), type_(type)
160 {
161 InitialisePlayer();
162 (void)Configure(volume_, loop_);
163 }
164
~RingtonePlayer()165 RingtonePlayer::~RingtonePlayer()
166 {
167 if (player_ != nullptr) {
168 player_->Release();
169 player_ = nullptr;
170 callback_ = nullptr;
171 }
172 }
173
InitialisePlayer()174 void RingtonePlayer::InitialisePlayer()
175 {
176 player_ = Media::PlayerFactory::CreatePlayer();
177 CHECK_AND_RETURN_LOG(player_ != nullptr, "Failed to create ringtone player instance");
178
179 callback_ = std::make_shared<RingtonePlayerCallback>(*this);
180 CHECK_AND_RETURN_LOG(callback_ != nullptr, "Failed to create callback object");
181
182 player_->SetPlayerCallback(callback_);
183 ringtoneState_ = STATE_NEW;
184 configuredUri_ = "";
185 }
186
PrepareRingtonePlayer(bool isReInitNeeded)187 int32_t RingtonePlayer::PrepareRingtonePlayer(bool isReInitNeeded)
188 {
189 MEDIA_INFO_LOG("RingtonePlayer::%{public}s", __func__);
190 CHECK_AND_RETURN_RET_LOG(player_ != nullptr, ERR_INVALID_PARAM, "Ringtone player instance is null");
191
192 // fetch uri from kvstore
193 auto kvstoreUri = audioRingtoneMgr_.GetSystemRingtoneUri(context_, type_);
194 CHECK_AND_RETURN_RET_LOG(!kvstoreUri.empty(), ERR_INVALID_PARAM, "Failed to obtain ringtone uri for playing");
195
196 // If uri is different from from configure uri, reset the player
197 if (kvstoreUri != configuredUri_ || isReInitNeeded) {
198 (void)player_->Reset();
199
200 auto ret = player_->SetSource(kvstoreUri);
201 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "Set source failed %{public}d", ret);
202
203 ret = player_->PrepareAsync();
204 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "Prepare failed %{public}d", ret);
205
206 configuredUri_ = kvstoreUri;
207 ringtoneState_ = STATE_NEW;
208 }
209
210 return SUCCESS;
211 }
212
Configure(const float & volume,const bool & loop)213 int32_t RingtonePlayer::Configure(const float &volume, const bool &loop)
214 {
215 MEDIA_INFO_LOG("RingtonePlayer::%{public}s", __func__);
216
217 CHECK_AND_RETURN_RET_LOG(volume >= LOW_VOL && volume <= HIGH_VOL, ERR_INVALID_PARAM, "Volume level invalid");
218 CHECK_AND_RETURN_RET_LOG(player_ != nullptr && ringtoneState_ != STATE_INVALID, ERR_INVALID_PARAM, "no player_");
219
220 loop_ = loop;
221 volume_ = volume;
222
223 if (ringtoneState_ != STATE_NEW) {
224 (void)player_->SetVolume(volume_, volume_);
225 (void)player_->SetLooping(loop_);
226 }
227
228 (void)PrepareRingtonePlayer(false);
229
230 return SUCCESS;
231 }
232
Start()233 int32_t RingtonePlayer::Start()
234 {
235 MEDIA_INFO_LOG("RingtonePlayer::%{public}s", __func__);
236
237 CHECK_AND_RETURN_RET_LOG(player_ != nullptr && ringtoneState_ != STATE_INVALID, ERR_INVALID_PARAM, "no player_");
238
239 if (player_->IsPlaying() || isStartQueued_) {
240 MEDIA_ERR_LOG("Play in progress, cannot start now");
241 return ERROR;
242 }
243
244 // Player doesn't support play in stopped state. Hence reinitialise player for making start<-->stop to work
245 if (ringtoneState_ == STATE_STOPPED) {
246 (void)PrepareRingtonePlayer(true);
247 } else {
248 (void)PrepareRingtonePlayer(false);
249 }
250
251 if (ringtoneState_ == STATE_NEW) {
252 MEDIA_INFO_LOG("Start received before player preparing is finished");
253 isStartQueued_ = true;
254 return SUCCESS;
255 }
256
257 auto ret = player_->Play();
258 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERROR, "Start failed %{public}d", ret);
259
260 ringtoneState_ = STATE_RUNNING;
261
262 return SUCCESS;
263 }
264
Stop()265 int32_t RingtonePlayer::Stop()
266 {
267 MEDIA_INFO_LOG("RingtonePlayer::%{public}s", __func__);
268 CHECK_AND_RETURN_RET_LOG(player_ != nullptr && ringtoneState_ != STATE_INVALID, ERR_INVALID_PARAM, "no player_");
269
270 if (ringtoneState_ != STATE_STOPPED && player_->IsPlaying()) {
271 (void)player_->Stop();
272 }
273
274 ringtoneState_ = STATE_STOPPED;
275 isStartQueued_ = false;
276
277 return SUCCESS;
278 }
279
Release()280 int32_t RingtonePlayer::Release()
281 {
282 MEDIA_INFO_LOG("RingtonePlayer::%{public}s player", __func__);
283
284 if (player_ != nullptr) {
285 (void)player_->Release();
286 }
287
288 ringtoneState_ = STATE_RELEASED;
289 player_ = nullptr;
290 callback_ = nullptr;
291
292 return SUCCESS;
293 }
294
GetRingtoneState()295 RingtoneState RingtonePlayer::GetRingtoneState()
296 {
297 MEDIA_INFO_LOG("RingtonePlayer::%{public}s", __func__);
298 return ringtoneState_;
299 }
300
SetPlayerState(RingtoneState ringtoneState)301 void RingtonePlayer::SetPlayerState(RingtoneState ringtoneState)
302 {
303 CHECK_AND_RETURN_LOG(player_ != nullptr, "Ringtone player instance is null");
304
305 if (ringtoneState_ != RingtoneState::STATE_RELEASED) {
306 ringtoneState_ = ringtoneState;
307 }
308
309 if (ringtoneState_ == RingtoneState::STATE_PREPARED) {
310 MEDIA_INFO_LOG("Player prepared callback received. loop:%{public}d volume:%{public}f", loop_, volume_);
311
312 Media::Format format;
313 format.PutIntValue(Media::PlayerKeys::CONTENT_TYPE, CONTENT_TYPE_RINGTONE);
314 format.PutIntValue(Media::PlayerKeys::STREAM_USAGE, STREAM_USAGE_NOTIFICATION_RINGTONE);
315
316 (void)player_->SetParameter(format);
317 (void)player_->SetVolume(volume_, volume_);
318 (void)player_->SetLooping(loop_);
319
320 if (isStartQueued_) {
321 auto ret = player_->Play();
322 isStartQueued_ = false;
323 CHECK_AND_RETURN_LOG(ret == SUCCESS, "Play failed %{public}d", ret);
324 ringtoneState_ = RingtoneState::STATE_RUNNING;
325 }
326 }
327 }
328
GetAudioRendererInfo(AudioStandard::AudioRendererInfo & rendererInfo) const329 int32_t RingtonePlayer::GetAudioRendererInfo(AudioStandard::AudioRendererInfo &rendererInfo) const
330 {
331 MEDIA_INFO_LOG("RingtonePlayer::%{public}s", __func__);
332 rendererInfo.contentType = ContentType::CONTENT_TYPE_RINGTONE;
333 rendererInfo.streamUsage = StreamUsage::STREAM_USAGE_NOTIFICATION_RINGTONE;
334 rendererInfo.rendererFlags = 0;
335 return SUCCESS;
336 }
337
GetTitle()338 std::string RingtonePlayer::GetTitle()
339 {
340 MEDIA_INFO_LOG("RingtonePlayer::%{public}s", __func__);
341 CHECK_AND_RETURN_RET_LOG(context_ != nullptr, "", "context cannot be null");
342
343 auto ctxUri = make_unique<Uri>(Media::MEDIALIBRARY_DATA_URI);
344 CHECK_AND_RETURN_RET_LOG(ctxUri != nullptr, "", "failed to create context uri");
345
346 shared_ptr<AppExecFwk::DataAbilityHelper> helper = AppExecFwk::DataAbilityHelper::Creator(context_, move(ctxUri));
347 CHECK_AND_RETURN_RET_LOG(helper != nullptr, "", "Unable to create data ability helper");
348
349 Uri mediaLibUri(Media::MEDIALIBRARY_DATA_URI);
350
351 vector<string> columns = {};
352 columns.push_back(Media::MEDIA_DATA_DB_TITLE);
353
354 auto uri = audioRingtoneMgr_.GetSystemRingtoneUri(context_, type_);
355 DataAbilityPredicates predicates;
356 predicates.EqualTo(Media::MEDIA_DATA_DB_FILE_PATH, uri);
357
358 shared_ptr<AbsSharedResultSet> resultSet = nullptr;
359 resultSet = helper->Query(mediaLibUri, columns, predicates);
360 CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, "", "Unable to fetch details from path %s", uri.c_str());
361
362 int ret = resultSet->GoToFirstRow();
363 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, "", "Failed to obtain the record");
364
365 int32_t titleIndex(0);
366 string title("");
367 resultSet->GetColumnIndex(Media::MEDIA_DATA_DB_TITLE, titleIndex);
368 resultSet->GetString(titleIndex, title);
369
370 helper->Release();
371
372 return title;
373 }
374
375 // Callback class symbols
RingtonePlayerCallback(RingtonePlayer & ringtonePlayer)376 RingtonePlayerCallback::RingtonePlayerCallback(RingtonePlayer &ringtonePlayer) : ringtonePlayer_(ringtonePlayer)
377 {}
378
OnError(PlayerErrorType errorType,int32_t errorCode)379 void RingtonePlayerCallback::OnError(PlayerErrorType errorType, int32_t errorCode)
380 {
381 MEDIA_ERR_LOG("Error reported from media server %{public}d", errorCode);
382 }
383
OnInfo(PlayerOnInfoType type,int32_t extra,const Format & infoBody)384 void RingtonePlayerCallback::OnInfo(PlayerOnInfoType type, int32_t extra, const Format &infoBody)
385 {
386 if (type != INFO_TYPE_STATE_CHANGE) {
387 return;
388 }
389 state_ = static_cast<PlayerStates>(extra);
390
391 switch (state_) {
392 case PLAYER_STATE_ERROR:
393 ringtoneState_ = STATE_INVALID;
394 break;
395 case PLAYER_IDLE:
396 case PLAYER_INITIALIZED:
397 case PLAYER_PREPARING:
398 ringtoneState_ = STATE_NEW;
399 break;
400 case PLAYER_PREPARED:
401 ringtoneState_ = STATE_PREPARED;
402 break;
403 case PLAYER_STARTED:
404 ringtoneState_ = STATE_RUNNING;
405 break;
406 case PLAYER_PAUSED:
407 ringtoneState_ = STATE_PAUSED;
408 break;
409 case PLAYER_STOPPED:
410 case PLAYER_PLAYBACK_COMPLETE:
411 ringtoneState_ = STATE_STOPPED;
412 break;
413 default:
414 break;
415 }
416 ringtonePlayer_.SetPlayerState(ringtoneState_);
417 }
418 } // namesapce AudioStandard
419 } // namespace OHOS
420