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 "audio_haptic_player_impl.h"
17 #include "audio_haptic_sound_low_latency_impl.h"
18 #include "audio_haptic_sound_normal_impl.h"
19 
20 #include "audio_haptic_log.h"
21 #include "media_errors.h"
22 
23 namespace {
24 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_AUDIO_NAPI, "AudioHapticPlayerImpl"};
25 }
26 
27 namespace OHOS {
28 namespace Media {
29 const int32_t LOAD_WAIT_SECONDS = 2;
30 const int32_t LOAD_WAIT_SECONDS_FOR_LOOP = 40;
31 
32 std::mutex AudioHapticPlayerFactory::createPlayerMutex_;
33 
CreateAudioHapticPlayer(const AudioHapticPlayerParam & param)34 std::shared_ptr<AudioHapticPlayer> AudioHapticPlayerFactory::CreateAudioHapticPlayer(
35     const AudioHapticPlayerParam &param)
36 {
37     std::lock_guard<std::mutex> lock(createPlayerMutex_);
38     // Create audio haptic player using the param.
39     std::shared_ptr<AudioHapticPlayerImpl> audioHapticPlayer = std::make_shared<AudioHapticPlayerImpl>();
40     audioHapticPlayer->SetPlayerParam(param);
41     audioHapticPlayer->LoadPlayer();
42     return audioHapticPlayer;
43 }
44 
45 std::mutex AudioHapticSound::createAudioHapticSoundMutex_;
46 
CreateAudioHapticSound(const AudioLatencyMode & latencyMode,const std::string & audioUri,const bool & muteAudio,const AudioStandard::StreamUsage & streamUsage,const bool & parallelPlayFlag)47 std::shared_ptr<AudioHapticSound> AudioHapticSound::CreateAudioHapticSound(
48     const AudioLatencyMode &latencyMode, const std::string &audioUri, const bool &muteAudio,
49     const AudioStandard::StreamUsage &streamUsage, const bool &parallelPlayFlag)
50 {
51     if (latencyMode != AUDIO_LATENCY_MODE_NORMAL && latencyMode != AUDIO_LATENCY_MODE_FAST) {
52         MEDIA_LOGE("Invalid param: the latency mode %{public}d is unsupported.", latencyMode);
53         return nullptr;
54     }
55 
56     std::lock_guard<std::mutex> lock(createAudioHapticSoundMutex_);
57     std::shared_ptr<AudioHapticSound> audioHapticSound = nullptr;
58     switch (latencyMode) {
59         case AUDIO_LATENCY_MODE_NORMAL:
60             audioHapticSound = std::make_shared<AudioHapticSoundNormalImpl>(audioUri, muteAudio, streamUsage);
61             break;
62         case AUDIO_LATENCY_MODE_FAST:
63             audioHapticSound = std::make_shared<AudioHapticSoundLowLatencyImpl>(
64                 audioUri, muteAudio, streamUsage, parallelPlayFlag);
65             break;
66         default:
67             MEDIA_LOGE("Invalid param: the latency mode %{public}d is unsupported.", latencyMode);
68             break;
69     }
70     return audioHapticSound;
71 }
72 
AudioHapticPlayerImpl()73 AudioHapticPlayerImpl::AudioHapticPlayerImpl()
74     : latencyMode_(AUDIO_LATENCY_MODE_NORMAL),
75       muteAudio_(false),
76       muteHaptic_(false),
77       audioUri_("")
78 {
79 }
80 
~AudioHapticPlayerImpl()81 AudioHapticPlayerImpl::~AudioHapticPlayerImpl()
82 {
83     if (playerState_ != AudioHapticPlayerState::STATE_RELEASED) {
84         ReleaseVibrator();
85         ReleaseSound();
86     }
87 }
88 
SetPlayerParam(const AudioHapticPlayerParam & param)89 void AudioHapticPlayerImpl::SetPlayerParam(const AudioHapticPlayerParam &param)
90 {
91     muteAudio_ = param.options.muteAudio;
92     muteHaptic_ = param.options.muteHaptics;
93     parallelPlayFlag_ = param.options.parallelPlayFlag;
94     audioUri_ = param.audioUri;
95     hapticSource_ = param.hapticSource;
96     latencyMode_ = param.latencyMode;
97     streamUsage_ = param.streamUsage;
98 }
99 
LoadPlayer()100 void AudioHapticPlayerImpl::LoadPlayer()
101 {
102     // Load audio player
103     audioHapticSound_ = AudioHapticSound::CreateAudioHapticSound(
104         latencyMode_, audioUri_, muteAudio_, streamUsage_, parallelPlayFlag_);
105     CHECK_AND_RETURN_LOG(audioHapticSound_ != nullptr, "Failed to create audio haptic sound instance");
106     soundCallback_ = std::make_shared<AudioHapticSoundCallbackImpl>(shared_from_this());
107     (void)audioHapticSound_->SetAudioHapticSoundCallback(soundCallback_);
108 
109     // Load vibrator
110     audioHapticVibrator_ = AudioHapticVibrator::CreateAudioHapticVibrator(*this);
111     CHECK_AND_RETURN_LOG(audioHapticVibrator_ != nullptr, "Failed to create audio haptic vibrator instance");
112 }
113 
IsMuted(const AudioHapticType & audioHapticType) const114 bool AudioHapticPlayerImpl::IsMuted(const AudioHapticType &audioHapticType) const
115 {
116     if (audioHapticType == AUDIO_HAPTIC_TYPE_AUDIO) {
117         return muteAudio_;
118     } else if (audioHapticType == AUDIO_HAPTIC_TYPE_HAPTIC) {
119         return muteHaptic_;
120     }
121     MEDIA_LOGE("IsMuted: invalid audioHapticType %{public}d", audioHapticType);
122     return false;
123 }
124 
Prepare()125 int32_t AudioHapticPlayerImpl::Prepare()
126 {
127     int32_t result = MSERR_OK;
128     std::lock_guard<std::mutex> lock(audioHapticPlayerLock_);
129     CHECK_AND_RETURN_RET_LOG(audioHapticSound_ != nullptr, MSERR_INVALID_OPERATION,
130         "Audio haptic sound is nullptr");
131     CHECK_AND_RETURN_RET_LOG(audioUri_ != "", MSERR_OPEN_FILE_FAILED, "Invalid val: audio uri is empty");
132     result = audioHapticSound_->PrepareSound();
133     CHECK_AND_RETURN_RET_LOG(result == MSERR_OK, result, "Failed to load audio file");
134 
135     CHECK_AND_RETURN_RET_LOG(audioHapticVibrator_ != nullptr, MSERR_INVALID_OPERATION,
136         "Audio haptic vibrator is nullptr");
137     result = audioHapticVibrator_->PreLoad(hapticSource_, streamUsage_);
138     CHECK_AND_RETURN_RET_LOG(result == MSERR_OK, result, "Failed to load vobration file");
139 
140     playerState_ = AudioHapticPlayerState::STATE_PREPARED;
141     return MSERR_OK;
142 }
143 
Start()144 int32_t AudioHapticPlayerImpl::Start()
145 {
146     int32_t result = MSERR_OK;
147     std::lock_guard<std::mutex> lock(audioHapticPlayerLock_);
148 
149     CHECK_AND_RETURN_RET_LOG(audioHapticVibrator_ != nullptr, MSERR_INVALID_OPERATION,
150         "Audio haptic vibrator is nullptr");
151 
152     if (vibrateThread_ != nullptr && vibrateThread_->joinable()) {
153         vibrateThread_->join();
154         vibrateThread_.reset();
155     }
156     if (vibrateThread_ == nullptr) {
157         ResetVibrateState();
158         vibrateThread_ = std::make_shared<std::thread>([this] { StartVibrate(); });
159     }
160 
161     CHECK_AND_RETURN_RET_LOG(audioHapticSound_ != nullptr, MSERR_INVALID_OPERATION,
162         "Audio haptic sound is nullptr");
163     result = audioHapticSound_->StartSound();
164     CHECK_AND_RETURN_RET_LOG(result == MSERR_OK, result, "Failed to start sound.");
165 
166     playerState_ = AudioHapticPlayerState::STATE_RUNNING;
167     return result;
168 }
169 
Stop()170 int32_t AudioHapticPlayerImpl::Stop()
171 {
172     int32_t result = MSERR_OK;
173     std::lock_guard<std::mutex> lock(audioHapticPlayerLock_);
174 
175     CHECK_AND_RETURN_RET_LOG(audioHapticVibrator_ != nullptr, MSERR_INVALID_OPERATION,
176         "Audio haptic vibrator is nullptr");
177     StopVibrate();
178 
179     CHECK_AND_RETURN_RET_LOG(audioHapticSound_ != nullptr, MSERR_INVALID_OPERATION,
180         "Audio haptic sound is nullptr");
181     result = audioHapticSound_->StopSound();
182     CHECK_AND_RETURN_RET_LOG(result == MSERR_OK, result, "Failed to stop sound.");
183 
184     playerState_ = AudioHapticPlayerState::STATE_STOPPED;
185     return result;
186 }
187 
Release()188 int32_t AudioHapticPlayerImpl::Release()
189 {
190     std::lock_guard<std::mutex> lock(audioHapticPlayerLock_);
191     CHECK_AND_RETURN_RET_LOG(playerState_ != AudioHapticPlayerState::STATE_RELEASED, MSERR_OK,
192         "The audio haptic player has been released.");
193 
194     CHECK_AND_RETURN_RET_LOG(audioHapticVibrator_ != nullptr, MSERR_INVALID_OPERATION,
195         "Audio haptic vibrator is nullptr");
196     ReleaseVibrator();
197 
198     CHECK_AND_RETURN_RET_LOG(audioHapticSound_ != nullptr, MSERR_INVALID_OPERATION,
199         "Audio haptic sound is nullptr");
200     ReleaseSound();
201 
202     playerState_ = AudioHapticPlayerState::STATE_RELEASED;
203     return MSERR_OK;
204 }
205 
ReleaseVibrator()206 void AudioHapticPlayerImpl::ReleaseVibrator()
207 {
208     if (audioHapticVibrator_ != nullptr) {
209         audioHapticVibrator_->StopVibrate();
210     }
211     {
212         // When player is releasing,notify vibrate thread immediately
213         std::lock_guard<std::mutex> lockVibrate(waitStartVibrateMutex_);
214         isAudioPlayFirstFrame_ = true;
215         isVibrationStopped_ = true;
216         condStartVibrate_.notify_one();
217     }
218     if (vibrateThread_ != nullptr && vibrateThread_->joinable()) {
219         vibrateThread_->join();
220     }
221     vibrateThread_.reset();
222     if (audioHapticVibrator_ != nullptr) {
223         (void)audioHapticVibrator_->Release();
224         audioHapticVibrator_ = nullptr;
225     }
226 }
227 
ReleaseSound()228 void AudioHapticPlayerImpl::ReleaseSound()
229 {
230     if (audioHapticSound_ != nullptr) {
231         (void)audioHapticSound_->ReleaseSound();
232         audioHapticSound_ = nullptr;
233     }
234     soundCallback_ = nullptr;
235 }
236 
SetVolume(float volume)237 int32_t AudioHapticPlayerImpl::SetVolume(float volume)
238 {
239     MEDIA_LOGI("AudioHapticPlayerImpl::SetVolume %{public}f", volume);
240     if (volume < 0.0f || volume > 1.0f) {
241         MEDIA_LOGE("SetVolume: the volume value is invalid.");
242         return MSERR_INVALID_VAL;
243     }
244 
245     std::lock_guard<std::mutex> lock(audioHapticPlayerLock_);
246     int32_t result = MSERR_OK;
247     volume_ = volume;
248     if (audioHapticSound_ == nullptr) {
249         MEDIA_LOGW("Audio haptic sound is nullptr!");
250         return result;
251     }
252     float actualVolume = volume_ * (muteAudio_ ? 0 : 1);
253     result = audioHapticSound_->SetVolume(actualVolume);
254 
255     if (latencyMode_ == AUDIO_LATENCY_MODE_NORMAL &&
256         (streamUsage_ == AudioStandard::StreamUsage::STREAM_USAGE_VOICE_RINGTONE ||
257         streamUsage_ == AudioStandard::StreamUsage::STREAM_USAGE_RINGTONE) &&
258         playerState_ == AudioHapticPlayerState::STATE_RUNNING &&
259         std::abs(volume_ - 0.0f) <= std::numeric_limits<float>::epsilon()) {
260         // only for the call manager ringtone
261         StopVibrate();
262     }
263 
264     return result;
265 }
266 
SetHapticIntensity(float intensity)267 int32_t AudioHapticPlayerImpl::SetHapticIntensity(float intensity)
268 {
269     MEDIA_LOGI("AudioHapticPlayerImpl::SetHapticIntensity %{public}f", intensity);
270     if (intensity < 1.0f || intensity > 100.0f) {
271         MEDIA_LOGE("SetHapticIntensity: the intensity value is invalid.");
272         return MSERR_INVALID_VAL;
273     }
274 
275     std::lock_guard<std::mutex> lock(audioHapticPlayerLock_);
276     return audioHapticVibrator_->SetHapticIntensity(intensity);
277 }
278 
SetLoop(bool loop)279 int32_t AudioHapticPlayerImpl::SetLoop(bool loop)
280 {
281     MEDIA_LOGI("AudioHapticPlayerImpl::SetLoop %{public}d", loop);
282     std::lock_guard<std::mutex> lock(audioHapticPlayerLock_);
283     int32_t result = MSERR_OK;
284     loop_ = loop;
285     if (audioHapticSound_ == nullptr) {
286         MEDIA_LOGW("Audio haptic sound is nullptr!");
287         return result;
288     }
289     result = audioHapticSound_->SetLoop(loop);
290     return result;
291 }
292 
GetHapticsMode() const293 HapticsMode AudioHapticPlayerImpl::GetHapticsMode() const
294 {
295     return hapticsMode_;
296 }
297 
SetHapticsMode(HapticsMode hapticsMode)298 void AudioHapticPlayerImpl::SetHapticsMode(HapticsMode hapticsMode)
299 {
300     MEDIA_LOGI("AudioHapticPlayerImpl::SetHapticsMode %{public}d", hapticsMode);
301     std::lock_guard<std::mutex> lock(audioHapticPlayerLock_);
302     hapticsMode_ = hapticsMode;
303 }
304 
SetAudioHapticPlayerCallback(const std::shared_ptr<AudioHapticPlayerCallback> & playerCallback)305 int32_t AudioHapticPlayerImpl::SetAudioHapticPlayerCallback(
306     const std::shared_ptr<AudioHapticPlayerCallback> &playerCallback)
307 {
308     if (playerCallback == nullptr) {
309         MEDIA_LOGE("The audio haptic player callback is nullptr.");
310         return MSERR_INVALID_VAL;
311     }
312 
313     std::lock_guard<std::mutex> lock(audioHapticPlayerLock_);
314     audioHapticPlayerCallback_ = playerCallback;
315     return MSERR_OK;
316 }
317 
GetAudioCurrentTime()318 int32_t AudioHapticPlayerImpl::GetAudioCurrentTime()
319 {
320     CHECK_AND_RETURN_RET_LOG(audioHapticSound_ != nullptr, -1, "Audio haptic sound is nullptr");
321     return audioHapticSound_->GetAudioCurrentTime();
322 }
323 
StartVibrate()324 int32_t AudioHapticPlayerImpl::StartVibrate()
325 {
326     if (muteHaptic_) {
327         MEDIA_LOGI("StartVibrate: muteHaptic is true. No need to vibrate");
328         return MSERR_OK;
329     }
330 
331     MEDIA_LOGI("Enter StartVibrate()");
332     std::unique_lock<std::mutex> lockWait(waitStartVibrateMutex_);
333     do {
334         int32_t waitTime = loop_ ? LOAD_WAIT_SECONDS_FOR_LOOP : LOAD_WAIT_SECONDS;
335         bool waitResult = condStartVibrate_.wait_for(lockWait, std::chrono::seconds(waitTime),
336             [this]() { return isAudioPlayFirstFrame_ || isVibrationStopped_; });
337         if (!waitResult) {
338             MEDIA_LOGE("StartVibrate: Failed to start vibrate (time out).");
339             return MSERR_INVALID_OPERATION;
340         }
341         if (isVibrationStopped_) {
342             MEDIA_LOGI("StartVibrate: audio haptic player has been stopped.");
343             return MSERR_OK;
344         }
345 
346         isAudioPlayFirstFrame_ = false; // reset for next time.
347 
348         int32_t hapticDelay = audioHapticVibrator_->GetDelayTime();
349         int32_t delay = (static_cast<int32_t>(this->audioLatency_) - hapticDelay) > 0 ?
350             static_cast<int32_t>(this->audioLatency_) - hapticDelay : 0;
351         waitResult = condStartVibrate_.wait_for(lockWait, std::chrono::milliseconds(delay),
352             [this]() { return isVibrationStopped_; });
353         if (isVibrationStopped_) {
354             MEDIA_LOGI("StartVibrate: audio haptic player has been stopped.");
355             return MSERR_OK;
356         }
357         MEDIA_LOGI("The first frame of audio is about to start. Triggering the vibration.");
358         audioHapticVibrator_->StartVibrate(latencyMode_);
359     } while (loop_ && !isVibrationStopped_);
360 
361     return MSERR_OK;
362 }
363 
StopVibrate()364 void AudioHapticPlayerImpl::StopVibrate()
365 {
366     MEDIA_LOGI("Stop vibrate for audio haptic player right now.");
367     if (audioHapticVibrator_ != nullptr) {
368         audioHapticVibrator_->StopVibrate();
369     } else {
370         MEDIA_LOGW("The audio haptic vibrator is nullptr!");
371     }
372     {
373         std::lock_guard<std::mutex> lockVibrate(waitStartVibrateMutex_);
374         isVibrationStopped_ = true;
375         condStartVibrate_.notify_one();
376     }
377     if (vibrateThread_ != nullptr && vibrateThread_->joinable()) {
378         vibrateThread_->join();
379     }
380     vibrateThread_.reset();
381 }
382 
ResetVibrateState()383 void AudioHapticPlayerImpl::ResetVibrateState()
384 {
385     isVibrationStopped_ = false;
386     if (audioHapticVibrator_ != nullptr) {
387         audioHapticVibrator_->ResetStopState();
388     } else {
389         MEDIA_LOGW("The audio haptic vibrator is nullptr!");
390     }
391 }
392 
NotifyInterruptEvent(const AudioStandard::InterruptEvent & interruptEvent)393 void AudioHapticPlayerImpl::NotifyInterruptEvent(const AudioStandard::InterruptEvent &interruptEvent)
394 {
395     std::shared_ptr<AudioHapticPlayerCallback> cb = audioHapticPlayerCallback_.lock();
396     if (cb != nullptr) {
397         MEDIA_LOGI("NotifyInterruptEvent for napi object or caller");
398         cb->OnInterrupt(interruptEvent);
399     } else {
400         MEDIA_LOGE("NotifyInterruptEvent: audioHapticPlayerCallback_ is nullptr");
401     }
402 }
403 
NotifyEndOfStreamEvent()404 void AudioHapticPlayerImpl::NotifyEndOfStreamEvent()
405 {
406     MEDIA_LOGI("NotifyEndOfStreamEvent");
407     std::thread (HandleEndOfStreamEventThreadFunc, shared_from_this()).detach();
408     std::shared_ptr<AudioHapticPlayerCallback> cb = audioHapticPlayerCallback_.lock();
409     if (cb != nullptr) {
410         MEDIA_LOGI("NotifyEndOfStreamEvent for napi object or caller");
411         cb->OnEndOfStream();
412     } else {
413         MEDIA_LOGE("NotifyEndOfStreamEvent: audioHapticPlayerCallback_ is nullptr");
414     }
415 }
416 
HandleEndOfStreamEventThreadFunc(std::weak_ptr<AudioHapticPlayerImpl> player)417 void AudioHapticPlayerImpl::HandleEndOfStreamEventThreadFunc(std::weak_ptr<AudioHapticPlayerImpl> player)
418 {
419     std::shared_ptr<AudioHapticPlayerImpl> playerPtr = player.lock();
420     if (playerPtr != nullptr) {
421         playerPtr->HandleEndOfStreamEvent();
422     }
423 }
424 
HandleEndOfStreamEvent()425 void AudioHapticPlayerImpl::HandleEndOfStreamEvent()
426 {
427     std::lock_guard<std::mutex> lock(audioHapticPlayerLock_);
428     if (playerState_ == AudioHapticPlayerState::STATE_RELEASED) {
429         MEDIA_LOGE("The audio haptic player has been released!");
430         return;
431     }
432     StopVibrate();
433     playerState_ = AudioHapticPlayerState::STATE_STOPPED;
434 }
435 
NotifyErrorEvent(int32_t errCode)436 void AudioHapticPlayerImpl::NotifyErrorEvent(int32_t errCode)
437 {
438     std::shared_ptr<AudioHapticPlayerCallback> cb = audioHapticPlayerCallback_.lock();
439     if (cb != nullptr) {
440         MEDIA_LOGI("NotifyErrorEvent for napi object or caller. errCode: %{public}d", errCode);
441         cb->OnError(errCode);
442     } else {
443         MEDIA_LOGE("NotifyErrorEvent: audioHapticPlayerCallback_ is nullptr");
444     }
445 }
446 
NotifyStartVibrate(const uint64_t & latency)447 void AudioHapticPlayerImpl::NotifyStartVibrate(const uint64_t &latency)
448 {
449     std::lock_guard<std::mutex> lock(this->waitStartVibrateMutex_);
450     this->isAudioPlayFirstFrame_ = true;
451     this->audioLatency_ = latency;
452     this->condStartVibrate_.notify_one();
453 }
454 
455 // Callback class symbols
AudioHapticSoundCallbackImpl(std::shared_ptr<AudioHapticPlayerImpl> audioHapticPlayerImpl)456 AudioHapticSoundCallbackImpl::AudioHapticSoundCallbackImpl(std::shared_ptr<AudioHapticPlayerImpl> audioHapticPlayerImpl)
457     : audioHapticPlayerImpl_(audioHapticPlayerImpl) {}
458 
OnEndOfStream()459 void AudioHapticSoundCallbackImpl::OnEndOfStream()
460 {
461     MEDIA_LOGI("OnEndOfStream reported from audio haptic sound.");
462     std::shared_ptr<AudioHapticPlayerImpl> player = audioHapticPlayerImpl_.lock();
463     if (player == nullptr) {
464         MEDIA_LOGE("The audio haptic player has been released.");
465         return;
466     }
467     player->NotifyEndOfStreamEvent();
468 }
469 
OnError(int32_t errorCode)470 void AudioHapticSoundCallbackImpl::OnError(int32_t errorCode)
471 {
472     MEDIA_LOGE("OnError reported from audio haptic sound: %{public}d", errorCode);
473     std::shared_ptr<AudioHapticPlayerImpl> player = audioHapticPlayerImpl_.lock();
474     if (player == nullptr) {
475         MEDIA_LOGE("The audio haptic player has been released.");
476         return;
477     }
478     player->NotifyErrorEvent(errorCode);
479 }
480 
OnInterrupt(const AudioStandard::InterruptEvent & interruptEvent)481 void AudioHapticSoundCallbackImpl::OnInterrupt(const AudioStandard::InterruptEvent &interruptEvent)
482 {
483     MEDIA_LOGI("OnInterrupt from audio haptic sound. hintType: %{public}d", interruptEvent.hintType);
484     std::shared_ptr<AudioHapticPlayerImpl> player = audioHapticPlayerImpl_.lock();
485     if (player == nullptr) {
486         MEDIA_LOGE("The audio haptic player has been released.");
487         return;
488     }
489     player->NotifyInterruptEvent(interruptEvent);
490 }
491 
OnFirstFrameWriting(uint64_t latency)492 void AudioHapticSoundCallbackImpl::OnFirstFrameWriting(uint64_t latency)
493 {
494     MEDIA_LOGI("OnFirstFrameWriting from audio haptic sound. Latency %{public}" PRIu64 "", latency);
495     std::shared_ptr<AudioHapticPlayerImpl> player = audioHapticPlayerImpl_.lock();
496     if (player == nullptr) {
497         MEDIA_LOGE("The audio haptic player has been released.");
498         return;
499     }
500     player->NotifyStartVibrate(latency);
501 }
502 } // namesapce AudioStandard
503 } // namespace OHOS
504