• 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 "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