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 "system_tone_player_impl.h"
17
18 #include <fcntl.h>
19 #include <sys/stat.h>
20 #include <thread>
21
22 #include "audio_info.h"
23 #include "config_policy_utils.h"
24
25 #include "media_errors.h"
26 #include "system_sound_log.h"
27 #include "system_sound_vibrator.h"
28
29 using namespace std;
30 using namespace OHOS::AbilityRuntime;
31
32 namespace {
33 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_AUDIO_NAPI, "SystemTonePlayer"};
34 }
35
36 namespace OHOS {
37 namespace Media {
38 const std::string FDHEAD = "fd://";
39 const std::string AUDIO_FORMAT_STR = ".ogg";
40 const std::string HAPTIC_FORMAT_STR = ".json";
41 const int32_t MAX_STREAM_ID = 128;
42 const int32_t ERRCODE_OPERATION_NOT_ALLOWED = 5400102;
43 const int32_t ERRCODE_IOERROR = 5400103;
44 const int32_t ERRCODE_INVALID_PARAMS = 20700002;
45 const int32_t ERRCODE_UNSUPPORTED_OPERATION = 20700003;
46 const std::string GENTLE_HAPTIC_PATH = "/sys_prod/resource/media/haptics/gentle/synchronized/notifications";
47 const std::string RINGTONE_PATH = "/media/audio/";
48 const std::string STANDARD_HAPTICS_PATH = "/media/haptics/standard/synchronized/";
49 const std::string GENTLE_HAPTICS_PATH = "/media/haptics/gentle/synchronized/";
50 const std::string NON_SYNC_HAPTICS_PATH = "resource/media/haptics/standard/non-synchronized/";
51
FormateHapticUri(const std::string & audioUri,ToneHapticsFeature feature)52 static std::string FormateHapticUri(const std::string &audioUri, ToneHapticsFeature feature)
53 {
54 std::string hapticUri = audioUri;
55 if (feature == ToneHapticsFeature::GENTLE) {
56 hapticUri.replace(0, hapticUri.rfind("/"), GENTLE_HAPTIC_PATH);
57 }
58 hapticUri.replace(hapticUri.rfind(AUDIO_FORMAT_STR), AUDIO_FORMAT_STR.length(), HAPTIC_FORMAT_STR);
59 return hapticUri;
60 }
61
IsFileExisting(const std::string & fileUri)62 static bool IsFileExisting(const std::string &fileUri)
63 {
64 struct stat buffer;
65 return (stat(fileUri.c_str(), &buffer) == 0);
66 }
67
FindHapticUriByAudioUri(const std::string & audioUri,ToneHapticsFeature feature,bool & isSupported)68 static std::string FindHapticUriByAudioUri(const std::string &audioUri, ToneHapticsFeature feature,
69 bool &isSupported)
70 {
71 std::string hapticUri = "";
72 if (audioUri.length() <= AUDIO_FORMAT_STR.length() ||
73 audioUri.rfind(AUDIO_FORMAT_STR) != audioUri.length() - AUDIO_FORMAT_STR.length()) {
74 MEDIA_LOGW("invalid audio uri: %{public}s", audioUri.c_str());
75 isSupported = false;
76 return hapticUri;
77 }
78 // the end of default system tone uri is ".ogg"
79 hapticUri = FormateHapticUri(audioUri, feature);
80 isSupported = !hapticUri.empty() && IsFileExisting(hapticUri);
81 return hapticUri;
82 }
83
SystemTonePlayerImpl(const shared_ptr<Context> & context,SystemSoundManagerImpl & systemSoundMgr,SystemToneType systemToneType)84 SystemTonePlayerImpl::SystemTonePlayerImpl(const shared_ptr<Context> &context,
85 SystemSoundManagerImpl &systemSoundMgr, SystemToneType systemToneType)
86 : context_(context),
87 systemSoundMgr_(systemSoundMgr),
88 systemToneType_(systemToneType)
89 {
90 audioHapticManager_ = AudioHapticManagerFactory::CreateAudioHapticManager();
91 CHECK_AND_RETURN_LOG(audioHapticManager_ != nullptr, "Failed to get audio haptic manager");
92
93 if (InitDataShareHelper()) {
94 std::string systemToneUri = systemSoundMgr_.GetSystemToneUri(context_, systemToneType_);
95 InitPlayer(systemToneUri);
96 ReleaseDataShareHelper();
97 }
98 }
99
~SystemTonePlayerImpl()100 SystemTonePlayerImpl::~SystemTonePlayerImpl()
101 {
102 DeleteAllPlayer();
103 if (audioHapticManager_ != nullptr) {
104 ReleaseHapticsSourceIds();
105 audioHapticManager_ = nullptr;
106 }
107 ReleaseDataShareHelper();
108 }
109
GetDefaultNonSyncHapticsPath()110 std::string SystemTonePlayerImpl::GetDefaultNonSyncHapticsPath()
111 {
112 char buf[MAX_PATH_LEN];
113 char *path = GetOneCfgFile(NON_SYNC_HAPTICS_PATH.c_str(), buf, MAX_PATH_LEN);
114 if (path == nullptr || *path == '\0') {
115 MEDIA_LOGE("Failed to get default non-sync haptics path");
116 return "";
117 }
118 std::string filePath = path;
119 MEDIA_LOGI("Default non-sync haptics path [%{public}s]", filePath.c_str());
120 filePath = filePath + "Tick-tock.json";
121 return filePath;
122 }
123
IsSameHapticMaps(const std::map<ToneHapticsFeature,std::string> & hapticUriMap)124 bool SystemTonePlayerImpl::IsSameHapticMaps(const std::map<ToneHapticsFeature, std::string> &hapticUriMap)
125 {
126 if (hapticUriMap_.size() != hapticUriMap.size()) {
127 return false;
128 }
129 for (auto &[feature, hapticUri] : hapticUriMap) {
130 if (hapticUriMap_.find(feature) == hapticUriMap_.end()) {
131 return false;
132 }
133 if (hapticUriMap_[feature] != hapticUri) {
134 return false;
135 }
136 }
137 return true;
138 }
139
InitPlayer(const std::string & audioUri)140 int32_t SystemTonePlayerImpl::InitPlayer(const std::string &audioUri)
141 {
142 MEDIA_LOGI("Enter InitPlayer() with audio uri %{public}s", audioUri.c_str());
143
144 if (audioUri == NO_SYSTEM_SOUND) {
145 if (!configuredUri_.empty() && configuredUri_ == audioUri) {
146 MEDIA_LOGI("The right system tone uri has been registered. Return directly.");
147 systemToneState_ = SystemToneState::STATE_PREPARED;
148 return MSERR_OK;
149 }
150 defaultNonSyncHapticUri_ = GetDefaultNonSyncHapticsPath();
151 configuredUri_ = NO_SYSTEM_SOUND;
152 systemToneState_ = SystemToneState::STATE_NEW;
153 return MSERR_OK;
154 }
155
156 std::map<ToneHapticsFeature, std::string> hapticUriMap;
157 GetCurrentHapticSettings(audioUri, hapticUriMap);
158
159 if (configuredUri_ == audioUri && IsSameHapticMaps(hapticUriMap)) {
160 MEDIA_LOGI("The right system tone uri has been registered. Return directly.");
161 systemToneState_ = SystemToneState::STATE_PREPARED;
162 return MSERR_OK;
163 }
164
165 configuredUri_ = audioUri;
166 hapticUriMap_.swap(hapticUriMap);
167
168 ReleaseHapticsSourceIds();
169 // Get the haptic file uri according to the audio file uri.
170 InitHapticsSourceIds();
171
172 systemToneState_ = SystemToneState::STATE_NEW;
173 return MSERR_OK;
174 }
175
CreatePlayerWithOptions(const AudioHapticPlayerOptions & options)176 int32_t SystemTonePlayerImpl::CreatePlayerWithOptions(const AudioHapticPlayerOptions &options)
177 {
178 CHECK_AND_RETURN_RET_LOG(sourceIds_.find(hapticsFeature_) != sourceIds_.end(), MSERR_OPEN_FILE_FAILED,
179 "Failed to find suorce id");
180 CHECK_AND_RETURN_RET_LOG(audioHapticManager_ != nullptr, MSERR_OPEN_FILE_FAILED,
181 "AudioHapticManager_ is nullptr");
182 playerMap_[streamId_] = audioHapticManager_->CreatePlayer(sourceIds_[hapticsFeature_], options);
183 CHECK_AND_RETURN_RET_LOG(playerMap_[streamId_] != nullptr, MSERR_OPEN_FILE_FAILED,
184 "Failed to create system tone player instance");
185
186 callbackMap_[streamId_] = std::make_shared<SystemTonePlayerCallback>(streamId_, shared_from_this());
187 CHECK_AND_RETURN_RET_LOG(callbackMap_[streamId_] != nullptr, MSERR_OPEN_FILE_FAILED,
188 "Failed to create system tone player callback object");
189 (void)playerMap_[streamId_]->SetAudioHapticPlayerCallback(callbackMap_[streamId_]);
190 playerMap_[streamId_]->SetHapticsMode(hapticsMode_);
191
192 int32_t result = playerMap_[streamId_]->Prepare();
193 CHECK_AND_RETURN_RET_LOG(result == MSERR_OK, result,
194 "Failed to prepare for system tone player: %{public}d", result);
195 return MSERR_OK;
196 }
197
UpdateStreamId()198 void SystemTonePlayerImpl::UpdateStreamId()
199 {
200 // Update streamId_ and ensure that streamId_ has no player.
201 streamId_++;
202 if (streamId_ > MAX_STREAM_ID) {
203 streamId_ = 1;
204 }
205 if (playerMap_.count(streamId_) > 0) {
206 DeletePlayer(streamId_);
207 }
208 }
209
GetOptionsFromRingerMode()210 SystemToneOptions SystemTonePlayerImpl::GetOptionsFromRingerMode()
211 {
212 SystemToneOptions options = {false, false};
213 AudioStandard::AudioRingerMode ringerMode = systemSoundMgr_.GetRingerMode();
214 MEDIA_LOGI("Current ringer mode is %{public}d", ringerMode);
215 if (ringerMode == AudioStandard::AudioRingerMode::RINGER_MODE_SILENT) {
216 options.muteAudio = true;
217 options.muteHaptics = true;
218 } else if (ringerMode == AudioStandard::AudioRingerMode::RINGER_MODE_VIBRATE) {
219 options.muteAudio = true;
220 } else if (ringerMode == AudioStandard::AudioRingerMode::RINGER_MODE_NORMAL) {
221 bool hapticsSwitchStatus = systemSoundMgr_.CheckVibrateSwitchStatus();
222 options.muteHaptics = !hapticsSwitchStatus;
223 }
224 return options;
225 }
226
GetNewHapticUriForAudioUri(const std::string & audioUri,const std::string & ringtonePath,const std::string & hapticsPath)227 std::string SystemTonePlayerImpl::GetNewHapticUriForAudioUri(const std::string &audioUri,
228 const std::string &ringtonePath, const std::string& hapticsPath)
229 {
230 string hapticUri = audioUri;
231 size_t pos = hapticUri.find(ringtonePath);
232 if (pos == string::npos) {
233 return "";
234 }
235 hapticUri.replace(pos, ringtonePath.size(), hapticsPath);
236 if (hapticUri.length() > AUDIO_FORMAT_STR.length() &&
237 hapticUri.rfind(AUDIO_FORMAT_STR) == hapticUri.length() - AUDIO_FORMAT_STR.length()) {
238 hapticUri.replace(hapticUri.rfind(AUDIO_FORMAT_STR), AUDIO_FORMAT_STR.length(), HAPTIC_FORMAT_STR);
239 if (IsFileExisting(hapticUri)) {
240 return hapticUri;
241 }
242 }
243 return "";
244 }
245
GetNewHapticUriForAudioUri(const std::string & audioUri,std::map<ToneHapticsFeature,std::string> & hapticsUriMap)246 void SystemTonePlayerImpl::GetNewHapticUriForAudioUri(const std::string &audioUri,
247 std::map<ToneHapticsFeature, std::string> &hapticsUriMap)
248 {
249 supportedHapticsFeatures_.clear();
250 std::string currAudioUri = audioUri;
251 std::string hapticUri = GetNewHapticUriForAudioUri(audioUri, RINGTONE_PATH, STANDARD_HAPTICS_PATH);
252 if (hapticUri.empty()) {
253 currAudioUri = systemSoundMgr_.GetDefaultSystemToneUri(SYSTEM_TONE_TYPE_NOTIFICATION);
254 hapticUri = GetNewHapticUriForAudioUri(currAudioUri, RINGTONE_PATH, STANDARD_HAPTICS_PATH);
255 if (hapticUri.empty()) {
256 MEDIA_LOGW("Failed to find the default json file. Play system tone without vibration.");
257 isHapticUriEmpty_ = true;
258 return;
259 }
260 }
261 supportedHapticsFeatures_.push_back(ToneHapticsFeature::STANDARD);
262 hapticsUriMap[ToneHapticsFeature::STANDARD] = hapticUri;
263 MEDIA_LOGI("GetNewHapticUriForAudioUri: STANDARD hapticUri %{public}s ", hapticUri.c_str());
264 hapticUri = GetNewHapticUriForAudioUri(currAudioUri, RINGTONE_PATH, GENTLE_HAPTICS_PATH);
265 if (!hapticUri.empty()) {
266 supportedHapticsFeatures_.push_back(ToneHapticsFeature::GENTLE);
267 hapticsUriMap[ToneHapticsFeature::GENTLE] = hapticUri;
268 MEDIA_LOGI("GetNewHapticUriForAudioUri: GENTLE hapticUri %{public}s ", hapticUri.c_str());
269 }
270 }
271
GetHapticUriForAudioUri(const std::string & audioUri,std::map<ToneHapticsFeature,std::string> & hapticsUriMap)272 void SystemTonePlayerImpl::GetHapticUriForAudioUri(const std::string &audioUri,
273 std::map<ToneHapticsFeature, std::string> &hapticsUriMap)
274 {
275 supportedHapticsFeatures_.clear();
276 bool isSupported = false;
277 std::string currAudioUri = audioUri;
278 std::string hapticUri = FindHapticUriByAudioUri(currAudioUri, ToneHapticsFeature::STANDARD, isSupported);
279 if (!isSupported) {
280 MEDIA_LOGW("Failed to find the vibration json file for audioUri. Use the default json file.");
281 currAudioUri = systemSoundMgr_.GetDefaultSystemToneUri(SYSTEM_TONE_TYPE_NOTIFICATION);
282 hapticUri = FindHapticUriByAudioUri(currAudioUri, ToneHapticsFeature::STANDARD, isSupported);
283 if (!isSupported) {
284 MEDIA_LOGW("Failed to find the default json file. Play system tone without vibration.");
285 isHapticUriEmpty_ = true;
286 return;
287 }
288 }
289 supportedHapticsFeatures_.push_back(ToneHapticsFeature::STANDARD);
290 hapticsUriMap[ToneHapticsFeature::STANDARD] = hapticUri;
291 MEDIA_LOGI("GetHapticUriForAudioUri: STANDARD hapticUri %{public}s ", hapticUri.c_str());
292 hapticUri = FindHapticUriByAudioUri(currAudioUri, ToneHapticsFeature::GENTLE, isSupported);
293 if (isSupported) {
294 supportedHapticsFeatures_.push_back(ToneHapticsFeature::GENTLE);
295 hapticsUriMap[ToneHapticsFeature::GENTLE] = hapticUri;
296 MEDIA_LOGI("GetHapticUriForAudioUri: GENTLE hapticUri %{public}s ", hapticUri.c_str());
297 }
298 }
299
CreateDataShareHelper(int32_t systemAbilityId)300 static shared_ptr<DataShare::DataShareHelper> CreateDataShareHelper(int32_t systemAbilityId)
301 {
302 auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
303 if (saManager == nullptr) {
304 return nullptr;
305 }
306 auto remoteObj = saManager->GetSystemAbility(systemAbilityId);
307 if (remoteObj == nullptr) {
308 return nullptr;
309 }
310 return DataShare::DataShareHelper::Creator(remoteObj, RINGTONE_URI);
311 }
312
InitDataShareHelper()313 bool SystemTonePlayerImpl::InitDataShareHelper()
314 {
315 MEDIA_LOGD("Enter InitDataShareHelper()");
316 ReleaseDataShareHelper();
317 dataShareHelper_ = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID);
318 CHECK_AND_RETURN_RET_LOG(dataShareHelper_ != nullptr, false, "Failed to create dataShareHelper.");
319 return true;
320 }
321
ReleaseDataShareHelper()322 void SystemTonePlayerImpl::ReleaseDataShareHelper()
323 {
324 if (dataShareHelper_ != nullptr) {
325 MEDIA_LOGD("Enter ReleaseDataShareHelper()");
326 dataShareHelper_->Release();
327 dataShareHelper_ = nullptr;
328 }
329 }
330
ChangeUri(const std::string & uri)331 std::string SystemTonePlayerImpl::ChangeUri(const std::string &uri)
332 {
333 std::string systemtoneUri = uri;
334 CHECK_AND_RETURN_RET_LOG(dataShareHelper_ != nullptr, systemtoneUri, "Failed to init dataShareHelper_.");
335
336 DataShare::DatashareBusinessError businessError;
337 DataShare::DataSharePredicates queryPredicates;
338 Uri ringtonePathUri(RINGTONE_PATH_URI);
339 vector<string> columns = {{RINGTONE_COLUMN_TONE_ID}, {RINGTONE_COLUMN_DATA}};
340 queryPredicates.EqualTo(RINGTONE_COLUMN_DATA, uri);
341 auto resultSet = dataShareHelper_->Query(ringtonePathUri, queryPredicates, columns, &businessError);
342 auto results = make_unique<RingtoneFetchResult<RingtoneAsset>>(move(resultSet));
343 unique_ptr<RingtoneAsset> ringtoneAsset = results->GetFirstObject();
344 if (ringtoneAsset != nullptr) {
345 string uriStr = RINGTONE_PATH_URI + RINGTONE_SLASH_CHAR + to_string(ringtoneAsset->GetId());
346 MEDIA_LOGD("ChangeUri::Open systemtoneUri is %{public}s", uriStr.c_str());
347 Uri ofUri(uriStr);
348 int32_t fd = dataShareHelper_->OpenFile(ofUri, "r");
349 if (fd > 0) {
350 systemtoneUri = FDHEAD + to_string(fd);
351 }
352 }
353
354 resultSet == nullptr ? : resultSet->Close();
355 MEDIA_LOGI("SystemTonePlayerImpl::ChangeUri systemtoneUri is %{public}s", systemtoneUri.c_str());
356 return systemtoneUri;
357 }
358
ChangeHapticsUri(const std::string & hapticsUri)359 std::string SystemTonePlayerImpl::ChangeHapticsUri(const std::string &hapticsUri)
360 {
361 std::string newHapticsUri = hapticsUri;
362 CHECK_AND_RETURN_RET_LOG(dataShareHelper_ != nullptr, newHapticsUri, "Failed to init dataShareHelper_.");
363
364 DataShare::DatashareBusinessError businessError;
365 DataShare::DataSharePredicates queryPredicates;
366 Uri hapticsPathUri(VIBRATE_PATH_URI);
367 vector<string> columns = {{VIBRATE_COLUMN_VIBRATE_ID}, {VIBRATE_COLUMN_DATA}};
368 queryPredicates.EqualTo(RINGTONE_COLUMN_DATA, hapticsUri);
369 auto resultSet = dataShareHelper_->Query(hapticsPathUri, queryPredicates, columns, &businessError);
370 auto results = make_unique<RingtoneFetchResult<VibrateAsset>>(move(resultSet));
371
372 unique_ptr<VibrateAsset> vibrateAssetByUri = results->GetFirstObject();
373 if (vibrateAssetByUri != nullptr) {
374 string uriStr = VIBRATE_PATH_URI + RINGTONE_SLASH_CHAR + to_string(vibrateAssetByUri->GetId());
375 MEDIA_LOGD("ChangeHapticsUri::Open newHapticsUri is %{public}s", uriStr.c_str());
376 Uri ofUri(uriStr);
377 int32_t fd = dataShareHelper_->OpenFile(ofUri, "r");
378 if (fd > 0) {
379 newHapticsUri = FDHEAD + to_string(fd);
380 }
381 }
382
383 resultSet == nullptr ? : resultSet->Close();
384 MEDIA_LOGI("SystemTonePlayerImpl::ChangeHapticsUri newHapticsUri is %{public}s", newHapticsUri.c_str());
385 return newHapticsUri;
386 }
387
Prepare()388 int32_t SystemTonePlayerImpl::Prepare()
389 {
390 MEDIA_LOGI("Enter Prepare()");
391 std::lock_guard<std::mutex> lock(systemTonePlayerMutex_);
392 CHECK_AND_RETURN_RET_LOG(systemToneState_ != SystemToneState::STATE_RELEASED, MSERR_INVALID_STATE,
393 "System tone player has been released!");
394
395 if (!InitDataShareHelper()) {
396 return ERRCODE_IOERROR;
397 }
398 std::string audioUri = systemSoundMgr_.GetSystemToneUri(context_, systemToneType_);
399 int32_t result = InitPlayer(audioUri);
400 ReleaseDataShareHelper();
401 CHECK_AND_RETURN_RET_LOG(result == MSERR_OK, result,
402 "Failed to init player for system tone player: %{public}d", result);
403 systemToneState_ = SystemToneState::STATE_PREPARED;
404 return result;
405 }
406
Start()407 int32_t SystemTonePlayerImpl::Start()
408 {
409 MEDIA_LOGI("Enter Start()");
410 SystemToneOptions systemToneOptions = {false, false};
411 return Start(systemToneOptions);
412 }
413
Start(const SystemToneOptions & systemToneOptions)414 int32_t SystemTonePlayerImpl::Start(const SystemToneOptions &systemToneOptions)
415 {
416 MEDIA_LOGI("Enter Start() with systemToneOptions: muteAudio %{public}d, muteHaptics %{public}d",
417 systemToneOptions.muteAudio, systemToneOptions.muteHaptics);
418 std::lock_guard<std::mutex> lock(systemTonePlayerMutex_);
419 CHECK_AND_RETURN_RET_LOG(systemToneState_ != SystemToneState::STATE_RELEASED, MSERR_INVALID_STATE,
420 "System tone player has been released!");
421
422 int32_t result = MSERR_OK;
423 UpdateStreamId();
424 SystemToneOptions ringerModeOptions = GetOptionsFromRingerMode();
425 bool actualMuteAudio = ringerModeOptions.muteAudio || systemToneOptions.muteAudio ||
426 configuredUri_ == NO_SYSTEM_SOUND || std::abs(volume_) <= std::numeric_limits<float>::epsilon();
427 bool actualMuteHaptics = ringerModeOptions.muteHaptics || systemToneOptions.muteHaptics || isHapticUriEmpty_;
428 if (actualMuteAudio) {
429 // the audio of system tone player has been muted. Only start vibrator.
430 if (!actualMuteHaptics) {
431 std::string hapticUri = (configuredUri_ == NO_SYSTEM_SOUND) ?
432 defaultNonSyncHapticUri_ : hapticUriMap_[hapticsFeature_];
433 SystemSoundVibrator::StartVibratorForSystemTone(hapticUri);
434 }
435 return streamId_;
436 }
437 result = CreatePlayerWithOptions({actualMuteAudio, actualMuteHaptics});
438 CHECK_AND_RETURN_RET_LOG((result == MSERR_OK && playerMap_[streamId_] != nullptr), -1,
439 "Failed to create audio haptic player: %{public}d", result);
440
441 result = playerMap_[streamId_]->SetVolume(volume_);
442 result = playerMap_[streamId_]->Start();
443 CHECK_AND_RETURN_RET_LOG(result == MSERR_OK, -1,
444 "Failed to start audio haptic player: %{public}d", result);
445 return streamId_;
446 }
447
Stop(const int32_t & streamId)448 int32_t SystemTonePlayerImpl::Stop(const int32_t &streamId)
449 {
450 MEDIA_LOGI("Enter Stop() with streamId %{public}d", streamId);
451 std::lock_guard<std::mutex> lock(systemTonePlayerMutex_);
452 CHECK_AND_RETURN_RET_LOG(systemToneState_ != SystemToneState::STATE_RELEASED, MSERR_INVALID_STATE,
453 "System tone player has been released!");
454
455 if (playerMap_.count(streamId) == 0 || playerMap_[streamId] == nullptr) {
456 MEDIA_LOGW("The stream has been stopped or the id %{public}d is invalid.", streamId);
457 return MSERR_OK;
458 }
459
460 int32_t result = playerMap_[streamId]->Stop();
461 DeletePlayer(streamId);
462 CHECK_AND_RETURN_RET_LOG(result == MSERR_OK, MSERR_INVALID_OPERATION,
463 "Failed to stop audio haptic player: %{public}d", result);
464 return result;
465 }
466
Release()467 int32_t SystemTonePlayerImpl::Release()
468 {
469 MEDIA_LOGI("Enter Release()");
470 std::lock_guard<std::mutex> lock(systemTonePlayerMutex_);
471 if (systemToneState_ == SystemToneState::STATE_RELEASED) {
472 MEDIA_LOGW("System tone player has been released!");
473 return MSERR_OK;
474 }
475 DeleteAllPlayer();
476 streamId_ = 0;
477 configuredUri_ = "";
478
479 if (audioHapticManager_ != nullptr) {
480 ReleaseHapticsSourceIds();
481 audioHapticManager_ = nullptr;
482 }
483 hapticsFeature_ = ToneHapticsFeature::STANDARD;
484 volume_ = SYS_TONE_PLAYER_MAX_VOLUME;
485 systemToneState_ = SystemToneState::STATE_RELEASED;
486 return MSERR_OK;
487 }
488
GetTitle() const489 std::string SystemTonePlayerImpl::GetTitle() const
490 {
491 MEDIA_LOGI("Enter GetTitle()");
492 std::string uri = systemSoundMgr_.GetSystemToneUri(context_, systemToneType_);
493 return uri.substr(uri.find_last_of("/") + 1);
494 }
495
DeletePlayer(const int32_t & streamId)496 void SystemTonePlayerImpl::DeletePlayer(const int32_t &streamId)
497 {
498 MEDIA_LOGI("DeletePlayer for streamId %{public}d", streamId);
499 if (playerMap_.count(streamId) > 0) {
500 if (playerMap_[streamId] != nullptr) {
501 playerMap_[streamId]->Release();
502 }
503 playerMap_.erase(streamId);
504 }
505 if (callbackMap_.count(streamId) > 0) {
506 callbackMap_.erase(streamId);
507 }
508 MEDIA_LOGI("DeletePlayer. playerMap_.size() %{public}zu callbackMap_.size() %{public}zu ",
509 playerMap_.size(), callbackMap_.size());
510 }
511
DeleteAllPlayer()512 void SystemTonePlayerImpl::DeleteAllPlayer()
513 {
514 MEDIA_LOGI("Delete all audio haptic player!");
515 for (auto iter = playerMap_.begin(); iter != playerMap_.end(); iter++) {
516 if (iter->second != nullptr) {
517 iter->second->Release();
518 }
519 }
520 playerMap_.clear();
521 callbackMap_.clear();
522 }
523
NotifyEndofStreamEvent(const int32_t & streamId)524 void SystemTonePlayerImpl::NotifyEndofStreamEvent(const int32_t &streamId)
525 {
526 std::lock_guard<std::mutex> lock(systemTonePlayerMutex_);
527 // onPlayFinished for a stream.
528 DeletePlayer(streamId);
529 }
530
NotifyInterruptEvent(const int32_t & streamId,const AudioStandard::InterruptEvent & interruptEvent)531 void SystemTonePlayerImpl::NotifyInterruptEvent(const int32_t &streamId,
532 const AudioStandard::InterruptEvent &interruptEvent)
533 {
534 MEDIA_LOGW("Interrupt event is not supported for system tone player!");
535 }
536
537 // Callback class symbols
SystemTonePlayerCallback(int32_t streamId,std::shared_ptr<SystemTonePlayerImpl> systemTonePlayerImpl)538 SystemTonePlayerCallback::SystemTonePlayerCallback(int32_t streamId,
539 std::shared_ptr<SystemTonePlayerImpl> systemTonePlayerImpl)
540 {
541 streamId_ = streamId;
542 systemTonePlayerImpl_ = systemTonePlayerImpl;
543 }
544
OnInterrupt(const AudioStandard::InterruptEvent & interruptEvent)545 void SystemTonePlayerCallback::OnInterrupt(const AudioStandard::InterruptEvent &interruptEvent)
546 {
547 MEDIA_LOGI("OnInterrupt from audio haptic player: hintTye %{public}d", interruptEvent.hintType);
548 std::shared_ptr<SystemTonePlayerImpl> player = systemTonePlayerImpl_.lock();
549 if (player == nullptr) {
550 MEDIA_LOGE("The audio haptic player has been released.");
551 return;
552 }
553 player->NotifyInterruptEvent(streamId_, interruptEvent);
554 }
555
OnEndOfStream(void)556 void SystemTonePlayerCallback::OnEndOfStream(void)
557 {
558 MEDIA_LOGI("OnEndOfStream from audio haptic player. StreamId %{public}d", streamId_);
559 std::shared_ptr<SystemTonePlayerImpl> player = systemTonePlayerImpl_.lock();
560 if (player == nullptr) {
561 MEDIA_LOGE("The audio haptic player has been released.");
562 return;
563 }
564 player->NotifyEndofStreamEvent(streamId_);
565 }
566
OnError(int32_t errorCode)567 void SystemTonePlayerCallback::OnError(int32_t errorCode)
568 {
569 MEDIA_LOGI("OnError from audio haptic player. errorCode %{public}d", errorCode);
570 }
571
IsValidVolume(float & scale)572 static bool IsValidVolume(float &scale)
573 {
574 static float eps = 1e-5;
575 static float maxVal = 1;
576 static float minVal = 0;
577 if (scale >= minVal || scale <= maxVal) {
578 return true;
579 }
580 if (scale > maxVal && abs(scale - maxVal) < eps) {
581 scale = maxVal;
582 return true;
583 }
584 if (scale < minVal && abs(scale - minVal) < eps) {
585 scale = minVal;
586 return true;
587 }
588 return false;
589 }
590
SetAudioVolume(float volume)591 int32_t SystemTonePlayerImpl::SetAudioVolume(float volume)
592 {
593 CHECK_AND_RETURN_RET_LOG(systemToneState_ != SystemToneState::STATE_RELEASED, ERRCODE_OPERATION_NOT_ALLOWED,
594 "System tone player has been released!");
595 CHECK_AND_RETURN_RET_LOG(IsValidVolume(volume), ERRCODE_INVALID_PARAMS,
596 "Invliad volume, the volume must be in the [0, 1] range");
597 volume_ = volume;
598 return MSERR_OK;
599 }
600
GetAudioVolume(float & recvValue)601 int32_t SystemTonePlayerImpl::GetAudioVolume(float &recvValue)
602 {
603 recvValue = volume_;
604 return MSERR_OK;
605 }
606
GetSupportHapticsFeatures(std::vector<ToneHapticsFeature> & recvFeatures)607 int32_t SystemTonePlayerImpl::GetSupportHapticsFeatures(std::vector<ToneHapticsFeature> &recvFeatures)
608 {
609 CHECK_AND_RETURN_RET_LOG(systemToneState_ != SystemToneState::STATE_RELEASED, ERRCODE_UNSUPPORTED_OPERATION,
610 "System tone player has been released!");
611 recvFeatures = supportedHapticsFeatures_;
612 return MSERR_OK;
613 }
614
SetHapticsFeature(ToneHapticsFeature feature)615 int32_t SystemTonePlayerImpl::SetHapticsFeature(ToneHapticsFeature feature)
616 {
617 CHECK_AND_RETURN_RET_LOG(systemToneState_ != SystemToneState::STATE_RELEASED, ERRCODE_OPERATION_NOT_ALLOWED,
618 "System tone player has been released!");
619 CHECK_AND_RETURN_RET_LOG((feature == ToneHapticsFeature::STANDARD || feature == ToneHapticsFeature::GENTLE) &&
620 std::find(supportedHapticsFeatures_.begin(),
621 supportedHapticsFeatures_.end(), feature) != supportedHapticsFeatures_.end(),
622 ERRCODE_UNSUPPORTED_OPERATION, "Unsupport haptics features %{public}d", feature);
623 hapticsFeature_ = feature;
624 return MSERR_OK;
625 }
626
GetHapticsFeature(ToneHapticsFeature & feature)627 int32_t SystemTonePlayerImpl::GetHapticsFeature(ToneHapticsFeature &feature)
628 {
629 CHECK_AND_RETURN_RET_LOG(systemToneState_ != SystemToneState::STATE_RELEASED, ERRCODE_UNSUPPORTED_OPERATION,
630 "System tone player has been released!");
631 feature = hapticsFeature_;
632 return MSERR_OK;
633 }
634
ConvertToToneHapticsType(SystemToneType type)635 ToneHapticsType SystemTonePlayerImpl::ConvertToToneHapticsType(SystemToneType type)
636 {
637 switch (type) {
638 case SystemToneType::SYSTEM_TONE_TYPE_SIM_CARD_0:
639 return ToneHapticsType::TEXT_MESSAGE_SIM_CARD_0;
640 case SystemToneType::SYSTEM_TONE_TYPE_SIM_CARD_1:
641 return ToneHapticsType::TEXT_MESSAGE_SIM_CARD_1;
642 case SystemToneType::SYSTEM_TONE_TYPE_NOTIFICATION:
643 return ToneHapticsType::NOTIFICATION;
644 default:
645 return ToneHapticsType::NOTIFICATION;
646 }
647 }
648
ConvertToHapticsMode(ToneHapticsMode toneHapticsMode)649 HapticsMode SystemTonePlayerImpl::ConvertToHapticsMode(ToneHapticsMode toneHapticsMode)
650 {
651 switch (toneHapticsMode) {
652 case ToneHapticsMode::NONE:
653 return HapticsMode::HAPTICS_MODE_NONE;
654 case ToneHapticsMode::SYNC:
655 return HapticsMode::HAPTICS_MODE_SYNC;
656 case ToneHapticsMode::NON_SYNC:
657 return HapticsMode::HAPTICS_MODE_NON_SYNC;
658 default:
659 return HapticsMode::HAPTICS_MODE_INVALID;
660 }
661 }
662
GetNewHapticSettings(const std::string & audioUri,std::map<ToneHapticsFeature,std::string> & hapticsUris)663 void SystemTonePlayerImpl::GetNewHapticSettings(const std::string &audioUri,
664 std::map<ToneHapticsFeature, std::string> &hapticsUris)
665 {
666 supportedHapticsFeatures_.clear();
667 ToneHapticsSettings settings;
668 int32_t result = systemSoundMgr_.GetToneHapticsSettings(dataShareHelper_, audioUri,
669 ConvertToToneHapticsType(systemToneType_), settings);
670 if (result != 0) {
671 MEDIA_LOGW("GetNewHapticSettings: get haptic settings fail");
672 return;
673 }
674 hapticsMode_ = ConvertToHapticsMode(settings.mode);
675 supportedHapticsFeatures_.push_back(ToneHapticsFeature::STANDARD);
676 hapticsUris[ToneHapticsFeature::STANDARD] = settings.hapticsUri;
677 MEDIA_LOGI("GetHapticUriForAudioUri: STANDARD hapticUri %{public}s ", settings.hapticsUri.c_str());
678 std::string hapticUri = systemSoundMgr_.GetHapticsUriByStyle(dataShareHelper_, settings.hapticsUri,
679 HapticsStyle::HAPTICS_STYLE_GENTLE);
680 if (!hapticUri.empty()) {
681 supportedHapticsFeatures_.push_back(ToneHapticsFeature::GENTLE);
682 hapticsUris[ToneHapticsFeature::GENTLE] = hapticUri;
683 MEDIA_LOGI("GetHapticUriForAudioUri: GENTLE hapticUri %{public}s ", hapticUri.c_str());
684 }
685 }
686
GetCurrentHapticSettings(const std::string & audioUri,std::map<ToneHapticsFeature,std::string> & hapticUriMap)687 void SystemTonePlayerImpl::GetCurrentHapticSettings(const std::string &audioUri,
688 std::map<ToneHapticsFeature, std::string> &hapticUriMap)
689 {
690 GetNewHapticSettings(audioUri, hapticUriMap);
691 if (hapticUriMap.empty()) {
692 hapticsMode_ = HapticsMode::HAPTICS_MODE_SYNC;
693 GetNewHapticUriForAudioUri(audioUri, hapticUriMap);
694 if (hapticUriMap.empty()) {
695 GetHapticUriForAudioUri(audioUri, hapticUriMap);
696 }
697 }
698 }
699
RegisterSource(const std::string & audioUri,const std::string & hapticUri)700 int32_t SystemTonePlayerImpl::RegisterSource(const std::string &audioUri, const std::string &hapticUri)
701 {
702 string newAudioUri = ChangeUri(audioUri);
703 string newHapticUri = ChangeHapticsUri(hapticUri);
704
705 int32_t sourceId = audioHapticManager_->RegisterSource(newAudioUri, newHapticUri);
706
707 const std::string fdHead = "fd://";
708 if (newAudioUri.find(fdHead) != std::string::npos) {
709 int32_t fd = atoi(newAudioUri.substr(fdHead.size()).c_str());
710 if (fd > 0) {
711 close(fd);
712 }
713 }
714 if (newHapticUri.find(fdHead) != std::string::npos) {
715 int32_t fd = atoi(newHapticUri.substr(fdHead.size()).c_str());
716 if (fd > 0) {
717 close(fd);
718 }
719 }
720
721 return sourceId;
722 }
723
InitHapticsSourceIds()724 void SystemTonePlayerImpl::InitHapticsSourceIds()
725 {
726 if (audioHapticManager_ == nullptr) {
727 return;
728 }
729
730 int32_t sourceId;
731 for (auto it = hapticUriMap_.begin(); it != hapticUriMap_.end(); ++it) {
732 MEDIA_LOGI("InitHapticsSourceIds%{public}d: ToneUri:%{public}s, hapticsUri:%{public}s, mode:%{public}d.",
733 it->first, configuredUri_.c_str(), it->second.c_str(), hapticsMode_);
734 sourceId = RegisterSource(configuredUri_, it->second);
735 CHECK_AND_CONTINUE_LOG(sourceId != -1, "Failed to register source for audio haptic manager");
736 (void)audioHapticManager_->SetAudioLatencyMode(sourceId, AUDIO_LATENCY_MODE_NORMAL);
737 (void)audioHapticManager_->SetStreamUsage(sourceId, AudioStandard::StreamUsage::STREAM_USAGE_NOTIFICATION);
738 sourceIds_[it->first] = sourceId;
739 }
740 }
741
ReleaseHapticsSourceIds()742 void SystemTonePlayerImpl::ReleaseHapticsSourceIds()
743 {
744 for (auto it = sourceIds_.begin(); it != sourceIds_.end(); ++it) {
745 if (it->second != -1) {
746 (void)audioHapticManager_->UnregisterSource(it->second);
747 it->second = -1;
748 }
749 }
750 }
751 } // namesapce AudioStandard
752 } // namespace OHOS
753