• 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 "config_policy_utils.h"
24 
25 #include "system_sound_log.h"
26 #include "media_errors.h"
27 #include "system_sound_vibrator.h"
28 
29 using namespace std;
30 using namespace OHOS::AbilityRuntime;
31 
32 namespace {
33 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_AUDIO_NAPI, "SystemTonePlayer"};
34 }
35 
36 namespace OHOS {
37 namespace Media {
38 const std::string FDHEAD = "fd://";
39 const std::string AUDIO_FORMAT_STR = ".ogg";
40 const std::string HAPTIC_FORMAT_STR = ".json";
41 const int32_t MAX_STREAM_ID = 128;
42 const std::string NON_SYNC_HAPTICS_PATH = "resource/media/haptics/standard/non-synchronized/";
43 
SystemTonePlayerImpl(const shared_ptr<Context> & context,SystemSoundManagerImpl & systemSoundMgr,SystemToneType systemToneType)44 SystemTonePlayerImpl::SystemTonePlayerImpl(const shared_ptr<Context> &context,
45     SystemSoundManagerImpl &systemSoundMgr, SystemToneType systemToneType)
46     : context_(context),
47       systemSoundMgr_(systemSoundMgr),
48       systemToneType_(systemToneType)
49 {
50     audioHapticManager_ = AudioHapticManagerFactory::CreateAudioHapticManager();
51     CHECK_AND_RETURN_LOG(audioHapticManager_ != nullptr, "Failed to get audio haptic manager");
52 
53     std::string systemToneUri = systemSoundMgr_.GetSystemToneUri(context_, systemToneType_);
54     InitPlayer(systemToneUri);
55 }
56 
~SystemTonePlayerImpl()57 SystemTonePlayerImpl::~SystemTonePlayerImpl()
58 {
59     DeleteAllPlayer();
60     if (audioHapticManager_ != nullptr) {
61         audioHapticManager_->UnregisterSource(sourceId_);
62         audioHapticManager_ = nullptr;
63     }
64 }
65 
GetDefaultNonSyncHapticsPath()66 std::string SystemTonePlayerImpl::GetDefaultNonSyncHapticsPath()
67 {
68     char buf[MAX_PATH_LEN];
69     char *path = GetOneCfgFile(NON_SYNC_HAPTICS_PATH.c_str(), buf, MAX_PATH_LEN);
70     if (path == nullptr || *path == '\0') {
71         MEDIA_LOGE("Failed to get default non-sync haptics path");
72         return "";
73     }
74     std::string filePath = path;
75     MEDIA_LOGI("Default non-sync haptics path [%{public}s]", filePath.c_str());
76     filePath = filePath + "Tick-tock.json";
77     return filePath;
78 }
79 
InitPlayer(const std::string & audioUri)80 int32_t SystemTonePlayerImpl::InitPlayer(const std::string &audioUri)
81 {
82     MEDIA_LOGI("Enter InitPlayer() with audio uri %{public}s", audioUri.c_str());
83 
84     if (sourceId_ != -1) {
85         (void)audioHapticManager_->UnregisterSource(sourceId_);
86         sourceId_ = -1;
87     }
88 
89     if (audioUri == NO_SYSTEM_SOUND) {
90         defaultNonSyncHapticUri_ = GetDefaultNonSyncHapticsPath();
91         configuredUri_ = NO_SYSTEM_SOUND;
92         systemToneState_ = SystemToneState::STATE_NEW;
93         return MSERR_OK;
94     }
95 
96     // Get the haptic file uri according to the audio file uri.
97     hapticUri_ = GetHapticUriForAudioUri(audioUri);
98     if (hapticUri_ == "") {
99         MEDIA_LOGW("haptic uri is empty. Play system tone without vibration");
100         isHapticUriEmpty_ = true;
101     }
102 
103     sourceId_ = audioHapticManager_->RegisterSource(ChangeUri(audioUri), hapticUri_);
104     CHECK_AND_RETURN_RET_LOG(sourceId_ != -1, MSERR_OPEN_FILE_FAILED,
105         "Failed to register source for audio haptic manager");
106     (void)audioHapticManager_->SetAudioLatencyMode(sourceId_, AUDIO_LATENCY_MODE_NORMAL);
107     (void)audioHapticManager_->SetStreamUsage(sourceId_, AudioStandard::StreamUsage::STREAM_USAGE_NOTIFICATION);
108 
109     configuredUri_ = audioUri;
110     systemToneState_ = SystemToneState::STATE_NEW;
111     return MSERR_OK;
112 }
113 
CreatePlayerWithOptions(const AudioHapticPlayerOptions & options)114 int32_t SystemTonePlayerImpl::CreatePlayerWithOptions(const AudioHapticPlayerOptions &options)
115 {
116     playerMap_[streamId_] = audioHapticManager_->CreatePlayer(sourceId_, options);
117     CHECK_AND_RETURN_RET_LOG(playerMap_[streamId_] != nullptr, MSERR_OPEN_FILE_FAILED,
118         "Failed to create system tone player instance");
119 
120     callbackMap_[streamId_] = std::make_shared<SystemTonePlayerCallback>(streamId_, shared_from_this());
121     CHECK_AND_RETURN_RET_LOG(callbackMap_[streamId_] != nullptr, MSERR_OPEN_FILE_FAILED,
122         "Failed to create system tone player callback object");
123     (void)playerMap_[streamId_]->SetAudioHapticPlayerCallback(callbackMap_[streamId_]);
124 
125     int32_t result = playerMap_[streamId_]->Prepare();
126     CHECK_AND_RETURN_RET_LOG(result == MSERR_OK, result,
127         "Failed to prepare for system tone player: %{public}d", result);
128     return MSERR_OK;
129 }
130 
UpdateStreamId()131 void SystemTonePlayerImpl::UpdateStreamId()
132 {
133     // Update streamId_ and ensure that streamId_ has no player.
134     streamId_++;
135     if (streamId_ > MAX_STREAM_ID) {
136         streamId_ = 1;
137     }
138     if (playerMap_.count(streamId_) > 0) {
139         DeletePlayer(streamId_);
140     }
141 }
142 
GetOptionsFromRingerMode()143 SystemToneOptions SystemTonePlayerImpl::GetOptionsFromRingerMode()
144 {
145     SystemToneOptions options = {false, false};
146     AudioStandard::AudioRingerMode ringerMode = systemSoundMgr_.GetRingerMode();
147     MEDIA_LOGI("Current ringer mode is %{public}d", ringerMode);
148     if (ringerMode == AudioStandard::AudioRingerMode::RINGER_MODE_SILENT) {
149         options.muteAudio = true;
150         options.muteHaptics = true;
151     } else if (ringerMode == AudioStandard::AudioRingerMode::RINGER_MODE_VIBRATE) {
152         options.muteAudio = true;
153     }
154     return options;
155 }
156 
GetHapticUriForAudioUri(const std::string & audioUri)157 std::string SystemTonePlayerImpl::GetHapticUriForAudioUri(const std::string &audioUri)
158 {
159     std::string hapticUri = "";
160     if (audioUri.length() > AUDIO_FORMAT_STR.length() &&
161         audioUri.rfind(AUDIO_FORMAT_STR) == audioUri.length() - AUDIO_FORMAT_STR.length()) {
162         // the end of audio uri is ".ogg"
163         hapticUri = audioUri;
164         hapticUri.replace(hapticUri.rfind(AUDIO_FORMAT_STR), AUDIO_FORMAT_STR.length(), HAPTIC_FORMAT_STR);
165     }
166 
167     if (hapticUri == "" || !IsFileExisting(hapticUri)) {
168         MEDIA_LOGW("Failed to find the vibration json file for audioUri. Use the default json file.");
169         std::string defaultSystemToneUri = systemSoundMgr_.GetDefaultSystemToneUri(SYSTEM_TONE_TYPE_NOTIFICATION);
170         if (defaultSystemToneUri.length() > AUDIO_FORMAT_STR.length() &&
171             defaultSystemToneUri.rfind(AUDIO_FORMAT_STR) == defaultSystemToneUri.length() - AUDIO_FORMAT_STR.length()) {
172             // the end of default system tone uri is ".ogg"
173             hapticUri = defaultSystemToneUri;
174             hapticUri.replace(hapticUri.rfind(AUDIO_FORMAT_STR), AUDIO_FORMAT_STR.length(), HAPTIC_FORMAT_STR);
175         } else {
176             MEDIA_LOGW("The default system tone uri is invalid!");
177         }
178     }
179 
180     return hapticUri;
181 }
182 
IsFileExisting(const std::string & fileUri)183 bool SystemTonePlayerImpl::IsFileExisting(const std::string &fileUri)
184 {
185     struct stat buffer;
186     return (stat(fileUri.c_str(), &buffer) == 0);
187 }
188 
CreateDataShareHelper(int32_t systemAbilityId)189 static shared_ptr<DataShare::DataShareHelper> CreateDataShareHelper(int32_t systemAbilityId)
190 {
191     auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
192     if (saManager == nullptr) {
193         return nullptr;
194     }
195     auto remoteObj = saManager->GetSystemAbility(systemAbilityId);
196     if (remoteObj == nullptr) {
197         return nullptr;
198     }
199     return DataShare::DataShareHelper::Creator(remoteObj, RINGTONE_URI);
200 }
201 
ChangeUri(const std::string & uri)202 std::string SystemTonePlayerImpl::ChangeUri(const std::string &uri)
203 {
204     std::string systemtoneUri = uri;
205     size_t found = uri.find(RINGTONE_CUSTOMIZED_BASE_PATH);
206     if (found != std::string::npos) {
207         std::shared_ptr<DataShare::DataShareHelper> dataShareHelper =
208             CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID);
209         CHECK_AND_RETURN_RET_LOG(dataShareHelper != nullptr, uri, "Failed to create dataShareHelper.");
210         DataShare::DatashareBusinessError businessError;
211         DataShare::DataSharePredicates queryPredicates;
212         Uri ringtonePathUri(RINGTONE_PATH_URI);
213         vector<string> columns = {{RINGTONE_COLUMN_TONE_ID}, {RINGTONE_COLUMN_DATA}};
214         queryPredicates.EqualTo(RINGTONE_COLUMN_DATA, uri);
215         auto resultSet = dataShareHelper->Query(ringtonePathUri, queryPredicates, columns, &businessError);
216         auto results = make_unique<RingtoneFetchResult<RingtoneAsset>>(move(resultSet));
217         unique_ptr<RingtoneAsset> ringtoneAsset = results->GetFirstObject();
218         if (ringtoneAsset != nullptr) {
219             string uriStr = RINGTONE_PATH_URI + RINGTONE_SLASH_CHAR + to_string(ringtoneAsset->GetId());
220             Uri ofUri(uriStr);
221             int32_t fd = dataShareHelper->OpenFile(ofUri, "r");
222             if (fd > 0) {
223                 systemtoneUri = FDHEAD + to_string(fd);
224             }
225         }
226         resultSet == nullptr ? : resultSet->Close();
227         dataShareHelper->Release();
228     }
229     MEDIA_LOGI("SystemTonePlayerImpl::ChangeUri systemtoneUri is %{public}s", systemtoneUri.c_str());
230     return systemtoneUri;
231 }
232 
Prepare()233 int32_t SystemTonePlayerImpl::Prepare()
234 {
235     MEDIA_LOGI("Enter Prepare()");
236     std::lock_guard<std::mutex> lock(systemTonePlayerMutex_);
237     CHECK_AND_RETURN_RET_LOG(systemToneState_ != SystemToneState::STATE_RELEASED, MSERR_INVALID_STATE,
238         "System tone player has been released!");
239 
240     std::string systemToneUri = systemSoundMgr_.GetSystemToneUri(context_, systemToneType_);
241     if (!configuredUri_.empty() && configuredUri_ == systemToneUri) {
242         MEDIA_LOGI("The right system tone uri has been registered. Return directly.");
243         systemToneState_ = SystemToneState::STATE_PREPARED;
244         return MSERR_OK;
245     }
246 
247     // reload audio haptic player for system tone.
248     int32_t result = InitPlayer(systemToneUri);
249     CHECK_AND_RETURN_RET_LOG(result == MSERR_OK, result,
250         "Failed to init player for system tone player: %{public}d", result);
251     systemToneState_ = SystemToneState::STATE_PREPARED;
252     return result;
253 }
254 
Start()255 int32_t SystemTonePlayerImpl::Start()
256 {
257     MEDIA_LOGI("Enter Start()");
258     SystemToneOptions systemToneOptions = {false, false};
259     return Start(systemToneOptions);
260 }
261 
Start(const SystemToneOptions & systemToneOptions)262 int32_t SystemTonePlayerImpl::Start(const SystemToneOptions &systemToneOptions)
263 {
264     MEDIA_LOGI("Enter Start() with systemToneOptions: muteAudio %{public}d, muteHaptics %{public}d",
265         systemToneOptions.muteAudio, systemToneOptions.muteHaptics);
266     std::lock_guard<std::mutex> lock(systemTonePlayerMutex_);
267     CHECK_AND_RETURN_RET_LOG(systemToneState_ != SystemToneState::STATE_RELEASED, MSERR_INVALID_STATE,
268         "System tone player has been released!");
269 
270     int32_t result = MSERR_OK;
271     UpdateStreamId();
272     SystemToneOptions ringerModeOptions = GetOptionsFromRingerMode();
273     bool actualMuteAudio = ringerModeOptions.muteAudio || systemToneOptions.muteAudio ||
274         configuredUri_ == NO_SYSTEM_SOUND;
275     bool actualMuteHaptics = ringerModeOptions.muteHaptics || systemToneOptions.muteHaptics || isHapticUriEmpty_;
276     if (actualMuteAudio) {
277         // the audio of system tone player has been muted. Only start vibrator.
278         if (!actualMuteHaptics) {
279             std::string hapticUri = (configuredUri_ == NO_SYSTEM_SOUND) ?
280                 defaultNonSyncHapticUri_ : hapticUri_;
281             SystemSoundVibrator::StartVibratorForSystemTone(hapticUri);
282         }
283         return streamId_;
284     }
285     result = CreatePlayerWithOptions({actualMuteAudio, actualMuteHaptics});
286     CHECK_AND_RETURN_RET_LOG((result == MSERR_OK && playerMap_[streamId_] != nullptr), -1,
287         "Failed to create audio haptic player: %{public}d", result);
288 
289     result = playerMap_[streamId_]->Start();
290     CHECK_AND_RETURN_RET_LOG(result == MSERR_OK, -1,
291         "Failed to start audio haptic player: %{public}d", result);
292     return streamId_;
293 }
294 
Stop(const int32_t & streamId)295 int32_t SystemTonePlayerImpl::Stop(const int32_t &streamId)
296 {
297     MEDIA_LOGI("Enter Stop() with streamId %{public}d", streamId);
298     std::lock_guard<std::mutex> lock(systemTonePlayerMutex_);
299     CHECK_AND_RETURN_RET_LOG(systemToneState_ != SystemToneState::STATE_RELEASED, MSERR_INVALID_STATE,
300         "System tone player has been released!");
301 
302     if (playerMap_.count(streamId) == 0 || playerMap_[streamId] == nullptr) {
303         MEDIA_LOGW("The stream has been stopped or the id %{public}d is invalid.", streamId);
304         return MSERR_OK;
305     }
306 
307     int32_t result = playerMap_[streamId]->Stop();
308     DeletePlayer(streamId);
309     CHECK_AND_RETURN_RET_LOG(result == MSERR_OK, MSERR_INVALID_OPERATION,
310         "Failed to stop audio haptic player: %{public}d", result);
311     return result;
312 }
313 
Release()314 int32_t SystemTonePlayerImpl::Release()
315 {
316     MEDIA_LOGI("Enter Release()");
317     std::lock_guard<std::mutex> lock(systemTonePlayerMutex_);
318     if (systemToneState_ == SystemToneState::STATE_RELEASED) {
319         MEDIA_LOGW("System tone player has been released!");
320         return MSERR_OK;
321     }
322     DeleteAllPlayer();
323     if (audioHapticManager_ != nullptr) {
324         audioHapticManager_->UnregisterSource(sourceId_);
325         audioHapticManager_ = nullptr;
326     }
327     sourceId_ = -1;
328     streamId_ = 0;
329     configuredUri_ = "";
330 
331     systemToneState_ = SystemToneState::STATE_RELEASED;
332     return MSERR_OK;
333 }
334 
GetTitle() const335 std::string SystemTonePlayerImpl::GetTitle() const
336 {
337     MEDIA_LOGI("Enter GetTitle()");
338     std::string uri = systemSoundMgr_.GetSystemToneUri(context_, systemToneType_);
339     return uri.substr(uri.find_last_of("/") + 1);
340 }
341 
DeletePlayer(const int32_t & streamId)342 void SystemTonePlayerImpl::DeletePlayer(const int32_t &streamId)
343 {
344     MEDIA_LOGI("DeletePlayer for streamId %{public}d", streamId);
345     if (playerMap_.count(streamId) > 0) {
346         if (playerMap_[streamId] != nullptr) {
347             playerMap_[streamId]->Release();
348         }
349         playerMap_.erase(streamId);
350     }
351     if (callbackMap_.count(streamId) > 0) {
352         callbackMap_.erase(streamId);
353     }
354     MEDIA_LOGI("DeletePlayer. playerMap_.size() %{public}zu  callbackMap_.size() %{public}zu ",
355         playerMap_.size(), callbackMap_.size());
356 }
357 
DeleteAllPlayer()358 void SystemTonePlayerImpl::DeleteAllPlayer()
359 {
360     MEDIA_LOGI("Delete all audio haptic player!");
361     for (auto iter = playerMap_.begin(); iter != playerMap_.end(); iter++) {
362         if (iter->second != nullptr) {
363             iter->second->Release();
364         }
365     }
366     playerMap_.clear();
367     callbackMap_.clear();
368 }
369 
NotifyEndofStreamEvent(const int32_t & streamId)370 void SystemTonePlayerImpl::NotifyEndofStreamEvent(const int32_t &streamId)
371 {
372     std::lock_guard<std::mutex> lock(systemTonePlayerMutex_);
373     // onPlayFinished for a stream.
374     DeletePlayer(streamId);
375 }
376 
NotifyInterruptEvent(const int32_t & streamId,const AudioStandard::InterruptEvent & interruptEvent)377 void SystemTonePlayerImpl::NotifyInterruptEvent(const int32_t &streamId,
378     const AudioStandard::InterruptEvent &interruptEvent)
379 {
380     MEDIA_LOGW("Interrupt event is not supported for system tone player!");
381 }
382 
383 // Callback class symbols
SystemTonePlayerCallback(int32_t streamId,std::shared_ptr<SystemTonePlayerImpl> systemTonePlayerImpl)384 SystemTonePlayerCallback::SystemTonePlayerCallback(int32_t streamId,
385     std::shared_ptr<SystemTonePlayerImpl> systemTonePlayerImpl)
386 {
387     streamId_ = streamId;
388     systemTonePlayerImpl_ = systemTonePlayerImpl;
389 }
390 
OnInterrupt(const AudioStandard::InterruptEvent & interruptEvent)391 void SystemTonePlayerCallback::OnInterrupt(const AudioStandard::InterruptEvent &interruptEvent)
392 {
393     MEDIA_LOGI("OnInterrupt from audio haptic player: hintTye %{public}d", interruptEvent.hintType);
394     std::shared_ptr<SystemTonePlayerImpl> player = systemTonePlayerImpl_.lock();
395     if (player == nullptr) {
396         MEDIA_LOGE("The audio haptic player has been released.");
397         return;
398     }
399     player->NotifyInterruptEvent(streamId_, interruptEvent);
400 }
401 
OnEndOfStream(void)402 void SystemTonePlayerCallback::OnEndOfStream(void)
403 {
404     MEDIA_LOGI("OnEndOfStream from audio haptic player. StreamId %{public}d", streamId_);
405     std::shared_ptr<SystemTonePlayerImpl> player = systemTonePlayerImpl_.lock();
406     if (player == nullptr) {
407         MEDIA_LOGE("The audio haptic player has been released.");
408         return;
409     }
410     player->NotifyEndofStreamEvent(streamId_);
411 }
412 
OnError(int32_t errorCode)413 void SystemTonePlayerCallback::OnError(int32_t errorCode)
414 {
415     MEDIA_LOGI("OnError from audio haptic player. errorCode %{public}d", errorCode);
416 }
417 } // namesapce AudioStandard
418 } // namespace OHOS
419