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