• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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