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