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