1 /*
2  * Copyright (c) 2024 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_sound_normal_impl.h"
17 
18 #include <fcntl.h>
19 
20 #include "audio_haptic_log.h"
21 #include "media_errors.h"
22 #include "player.h"
23 
24 namespace {
25 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_AUDIO_NAPI, "AudioHapticSoundNormalImpl"};
26 }
27 
28 namespace OHOS {
29 namespace Media {
30 const int32_t LOAD_WAIT_SECONDS = 2;
31 
AudioHapticSoundNormalImpl(const std::string & audioUri,const bool & muteAudio,const AudioStandard::StreamUsage & streamUsage)32 AudioHapticSoundNormalImpl::AudioHapticSoundNormalImpl(const std::string &audioUri, const bool &muteAudio,
33     const AudioStandard::StreamUsage &streamUsage)
34     : audioUri_(audioUri),
35       muteAudio_(muteAudio),
36       streamUsage_(streamUsage)
37 {
38 }
39 
~AudioHapticSoundNormalImpl()40 AudioHapticSoundNormalImpl::~AudioHapticSoundNormalImpl()
41 {
42     if (avPlayer_ != nullptr) {
43         ReleaseAVPlayer();
44     }
45 }
46 
LoadAVPlayer()47 int32_t AudioHapticSoundNormalImpl::LoadAVPlayer()
48 {
49     avPlayer_ = PlayerFactory::CreatePlayer();
50     CHECK_AND_RETURN_RET_LOG(avPlayer_ != nullptr, MSERR_INVALID_VAL, "Failed to create AvPlayer instance");
51 
52     avPlayerCallback_ = std::make_shared<AHSoundNormalCallback>(shared_from_this());
53     CHECK_AND_RETURN_RET_LOG(avPlayerCallback_ != nullptr, MSERR_INVALID_VAL, "Failed to create callback object");
54     avPlayer_->SetPlayerCallback(avPlayerCallback_);
55 
56     configuredAudioUri_ = "";
57     playerState_ = AudioHapticPlayerState::STATE_NEW;
58     return MSERR_OK;
59 }
60 
PrepareSound()61 int32_t AudioHapticSoundNormalImpl::PrepareSound()
62 {
63     MEDIA_LOGI("PrepareSound with AVPlayer");
64     std::lock_guard<std::mutex> lock(audioHapticPlayerLock_);
65     int32_t result = LoadAVPlayer();
66     CHECK_AND_RETURN_RET_LOG(result == MSERR_OK && avPlayer_ != nullptr, MSERR_INVALID_VAL,
67         "Audio haptic player(avplayer) instance is null");
68     CHECK_AND_RETURN_RET_LOG(!audioUri_.empty(), MSERR_OPEN_FILE_FAILED, "The audio uri is empty");
69     if (audioUri_ != configuredAudioUri_) {
70         return ResetAVPlayer();
71     }
72     return MSERR_OK;
73 }
74 
ResetAVPlayer()75 int32_t AudioHapticSoundNormalImpl::ResetAVPlayer()
76 {
77     // Reset the player and reload it.
78     MEDIA_LOGI("ResetAVPlayer");
79     (void)avPlayer_->Reset();
80     MEDIA_LOGI("Set audio source to avplayer. audioUri [%{public}s]", audioUri_.c_str());
81     const std::string fdHead = "fd://";
82 
83     if (audioUri_.find(fdHead) != std::string::npos) {
84         int32_t fd = atoi(audioUri_.substr(fdHead.size()).c_str());
85         CHECK_AND_RETURN_RET_LOG(fd > 0, MSERR_OPEN_FILE_FAILED, "Prepare: Failed to extract fd for avplayer.");
86         fileDes_ = dup(fd);
87         MEDIA_LOGI("fileDes_ == %{public}d", fileDes_);
88     } else {
89         char realPathRes[PATH_MAX + 1] = {'\0'};
90         CHECK_AND_RETURN_RET_LOG((strlen(audioUri_.c_str()) < PATH_MAX) &&
91             (realpath(audioUri_.c_str(), realPathRes) != nullptr), MSERR_UNSUPPORT_FILE, "Invalid file path length");
92         std::string realPathStr(realPathRes);
93         if (fileDes_ != -1) {
94             (void)close(fileDes_);
95             fileDes_ = -1;
96         }
97         fileDes_ = open(realPathStr.c_str(), O_RDONLY);
98         CHECK_AND_RETURN_RET_LOG(fileDes_ != -1, MSERR_OPEN_FILE_FAILED, "Prepare: Failed to open uri for avplayer.");
99     }
100     int32_t ret = avPlayer_->SetSource(fileDes_);
101     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_OPEN_FILE_FAILED, "Set source failed %{public}d", ret);
102 
103     Format format;
104     format.PutIntValue(PlayerKeys::CONTENT_TYPE, AudioStandard::CONTENT_TYPE_UNKNOWN);
105     format.PutIntValue(PlayerKeys::STREAM_USAGE, streamUsage_);
106     ret = avPlayer_->SetParameter(format);
107     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "Set stream usage to AVPlayer failed %{public}d", ret);
108 
109     ret = avPlayer_->PrepareAsync();
110     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "Prepare failed %{public}d", ret);
111 
112     std::unique_lock<std::mutex> lockPrepare(prepareMutex_);
113     prepareCond_.wait_for(lockPrepare, std::chrono::seconds(LOAD_WAIT_SECONDS),
114         [this]() { return isPrepared_ || isReleased_ || isUnsupportedFile_; });
115     CHECK_AND_RETURN_RET_LOG(!isReleased_, MSERR_INVALID_OPERATION, "The avplayer is released when it is preparing.");
116     CHECK_AND_RETURN_RET_LOG(!isUnsupportedFile_, MSERR_UNSUPPORT_FILE, "Unsupported file when preparing avplayer.");
117     CHECK_AND_RETURN_RET_LOG(isPrepared_, MSERR_OPEN_FILE_FAILED, "Failed to load audio uri: time out.");
118 
119     // The avplayer has been prepared.
120     float actualVolume = volume_ * (muteAudio_ ? 0 : 1);
121     MEDIA_LOGI("AVPlayer has been prepared. Set volume %{public}f and loop %{public}d.", actualVolume, loop_);
122     (void)avPlayer_->SetVolume(actualVolume, actualVolume);
123     (void)avPlayer_->SetLooping(loop_);
124 
125     configuredAudioUri_ = audioUri_;
126     playerState_ = AudioHapticPlayerState::STATE_PREPARED;
127     return MSERR_OK;
128 }
129 
130 
StartSound()131 int32_t AudioHapticSoundNormalImpl::StartSound()
132 {
133     MEDIA_LOGI("StartSound with AVPlayer");
134     std::lock_guard<std::mutex> lock(audioHapticPlayerLock_);
135     CHECK_AND_RETURN_RET_LOG(avPlayer_ != nullptr && playerState_ != AudioHapticPlayerState::STATE_INVALID,
136         MSERR_INVALID_VAL, "StartAVPlayer: no available AVPlayer_");
137     CHECK_AND_RETURN_RET_LOG(!audioUri_.empty(), MSERR_OPEN_FILE_FAILED, "The audio uri is empty");
138 
139     if (playerState_ == AudioHapticPlayerState::STATE_RUNNING) {
140         MEDIA_LOGE("The avplayer has been running. Cannot start again");
141         return MSERR_START_FAILED;
142     }
143 
144     // Player doesn't support play in stopped state. Hence reinitialise player for making start<-->stop to work
145     if (playerState_ == AudioHapticPlayerState::STATE_STOPPED || audioUri_ != configuredAudioUri_) {
146         ResetAVPlayer();
147     }
148     auto ret = avPlayer_->Play();
149     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_START_FAILED, "Start failed %{public}d", ret);
150 
151     playerState_ = AudioHapticPlayerState::STATE_RUNNING;
152     return MSERR_OK;
153 }
154 
StopSound()155 int32_t AudioHapticSoundNormalImpl::StopSound()
156 {
157     MEDIA_LOGI("StopSound with AVPlayer");
158     std::lock_guard<std::mutex> lock(audioHapticPlayerLock_);
159     CHECK_AND_RETURN_RET_LOG(avPlayer_ != nullptr && playerState_ != AudioHapticPlayerState::STATE_INVALID,
160         MSERR_INVALID_VAL, "StopAVPlayer: no available AVPlayer_");
161 
162     if (playerState_ != AudioHapticPlayerState::STATE_STOPPED) {
163         (void)avPlayer_->Stop();
164     }
165 
166     playerState_ = AudioHapticPlayerState::STATE_STOPPED;
167     return MSERR_OK;
168 }
169 
ReleaseSound()170 int32_t AudioHapticSoundNormalImpl::ReleaseSound()
171 {
172     MEDIA_LOGI("ReleaseSound with AVPlayer");
173     {
174         std::lock_guard<std::mutex> lockPrepare(prepareMutex_);
175         isReleased_ = true;
176         prepareCond_.notify_one();
177     }
178     std::lock_guard<std::mutex> lock(audioHapticPlayerLock_);
179     CHECK_AND_RETURN_RET_LOG(playerState_ != AudioHapticPlayerState::STATE_RELEASED, MSERR_OK,
180         "The audio haptic player for normal mode has been released.");
181     ReleaseAVPlayer();
182     playerState_ = AudioHapticPlayerState::STATE_RELEASED;
183     return MSERR_OK;
184 }
185 
ReleaseAVPlayer()186 void AudioHapticSoundNormalImpl::ReleaseAVPlayer()
187 {
188     if (avPlayer_ != nullptr) {
189         (void)avPlayer_->Release();
190         avPlayer_ = nullptr;
191     }
192     avPlayerCallback_ = nullptr;
193     if (fileDes_ != -1) {
194         (void)close(fileDes_);
195         fileDes_ = -1;
196     }
197 }
198 
SetVolume(float volume)199 int32_t AudioHapticSoundNormalImpl::SetVolume(float volume)
200 {
201     MEDIA_LOGI("AudioHapticSoundNormalImpl::SetVolume %{public}f", volume);
202     if (volume < 0.0f || volume > 1.0f) {
203         MEDIA_LOGE("SetVolume: the volume value is invalid.");
204         return MSERR_INVALID_VAL;
205     }
206 
207     std::lock_guard<std::mutex> lock(audioHapticPlayerLock_);
208     int32_t result = MSERR_OK;
209     volume_ = volume;
210 
211     if (playerState_ != AudioHapticPlayerState::STATE_PREPARED &&
212         playerState_ != AudioHapticPlayerState::STATE_RUNNING) {
213         MEDIA_LOGI("Audio haptic player is not prepared or running. No need to modify player");
214         return result;
215     }
216 
217     float actualVolume = volume_ * (muteAudio_ ? 0 : 1);
218     result = avPlayer_->SetVolume(actualVolume, actualVolume);
219     return result;
220 }
221 
SetLoop(bool loop)222 int32_t AudioHapticSoundNormalImpl::SetLoop(bool loop)
223 {
224     MEDIA_LOGI("AudioHapticSoundNormalImpl::SetLoop %{public}d", loop);
225     std::lock_guard<std::mutex> lock(audioHapticPlayerLock_);
226     int32_t result = MSERR_OK;
227     loop_ = loop;
228 
229     if (playerState_ != AudioHapticPlayerState::STATE_PREPARED &&
230         playerState_ != AudioHapticPlayerState::STATE_RUNNING) {
231         MEDIA_LOGI("Audio haptic player is not prepared or running. No need to modify player");
232         return result;
233     }
234 
235     result = avPlayer_->SetLooping(loop_);
236     return result;
237 }
238 
GetAudioCurrentTime()239 int32_t AudioHapticSoundNormalImpl::GetAudioCurrentTime()
240 {
241     if (avPlayer_ == nullptr) {
242         MEDIA_LOGE("GetAudioCurrentTime: avPlayer_ is nullptr. This function is only usable for avPlayer.");
243         return -1;
244     }
245     int32_t currentTime = -1;
246     (void)avPlayer_->GetCurrentTime(currentTime);
247     return currentTime;
248 }
249 
SetAudioHapticSoundCallback(const std::shared_ptr<AudioHapticSoundCallback> & callback)250 int32_t AudioHapticSoundNormalImpl::SetAudioHapticSoundCallback(
251     const std::shared_ptr<AudioHapticSoundCallback> &callback)
252 {
253     if (callback == nullptr) {
254         MEDIA_LOGE("The audio haptic player callback is nullptr.");
255         return MSERR_INVALID_VAL;
256     }
257 
258     std::lock_guard<std::mutex> lock(audioHapticPlayerLock_);
259     audioHapticPlayerCallback_ = callback;
260     return MSERR_OK;
261 }
262 
SetAVPlayerState(AudioHapticPlayerState playerState)263 void AudioHapticSoundNormalImpl::SetAVPlayerState(AudioHapticPlayerState playerState)
264 {
265     MEDIA_LOGI("SetAVPlayerState, state %{public}d", playerState);
266     playerState_ = playerState;
267 }
268 
NotifyPreparedEvent()269 void AudioHapticSoundNormalImpl::NotifyPreparedEvent()
270 {
271     std::lock_guard<std::mutex> lockPrepare(prepareMutex_);
272     isPrepared_ = true;
273     prepareCond_.notify_one();
274 }
275 
NotifyErrorEvent(int32_t errorCode)276 void AudioHapticSoundNormalImpl::NotifyErrorEvent(int32_t errorCode)
277 {
278     MediaServiceErrCode mediaErr = static_cast<MediaServiceErrCode>(errorCode);
279     if (mediaErr == MSERR_UNSUPPORT_FILE) {
280         std::lock_guard<std::mutex> lockPrepare(prepareMutex_);
281         isUnsupportedFile_ = true;
282         prepareCond_.notify_one();
283     }
284 
285     std::shared_ptr<AudioHapticSoundCallback> cb = audioHapticPlayerCallback_.lock();
286     if (cb != nullptr) {
287         MEDIA_LOGI("NotifyFirstFrameEvent for audio haptic player");
288         cb->OnError(errorCode);
289     } else {
290         MEDIA_LOGE("NotifyFirstFrameEvent: audioHapticPlayerCallback_ is nullptr");
291     }
292 }
293 
NotifyFirstFrameEvent(uint64_t latency)294 void AudioHapticSoundNormalImpl::NotifyFirstFrameEvent(uint64_t latency)
295 {
296     std::shared_ptr<AudioHapticSoundCallback> cb = audioHapticPlayerCallback_.lock();
297     if (cb != nullptr) {
298         MEDIA_LOGI("NotifyFirstFrameEvent for audio haptic player");
299         cb->OnFirstFrameWriting(latency);
300     } else {
301         MEDIA_LOGE("NotifyFirstFrameEvent: audioHapticPlayerCallback_ is nullptr");
302     }
303 }
304 
NotifyInterruptEvent(AudioStandard::InterruptEvent & interruptEvent)305 void AudioHapticSoundNormalImpl::NotifyInterruptEvent(AudioStandard::InterruptEvent &interruptEvent)
306 {
307     std::shared_ptr<AudioHapticSoundCallback> cb = audioHapticPlayerCallback_.lock();
308     if (cb != nullptr) {
309         MEDIA_LOGI("NotifyInterruptEvent for audio haptic player");
310         cb->OnInterrupt(interruptEvent);
311     } else {
312         MEDIA_LOGE("NotifyInterruptEvent: audioHapticPlayerCallback_ is nullptr");
313     }
314 }
315 
NotifyEndOfStreamEvent()316 void AudioHapticSoundNormalImpl::NotifyEndOfStreamEvent()
317 {
318     MEDIA_LOGI("NotifyEndOfStreamEvent");
319     playerState_ = AudioHapticPlayerState::STATE_STOPPED;
320     std::shared_ptr<AudioHapticSoundCallback> cb = audioHapticPlayerCallback_.lock();
321     if (cb != nullptr) {
322         MEDIA_LOGI("NotifyEndOfStreamEvent for audio haptic player");
323         cb->OnEndOfStream();
324     } else {
325         MEDIA_LOGE("NotifyEndOfStreamEvent: audioHapticPlayerCallback_ is nullptr");
326     }
327 }
328 
329 // Callback class symbols
AHSoundNormalCallback(std::shared_ptr<AudioHapticSoundNormalImpl> soundNormalImpl)330 AHSoundNormalCallback::AHSoundNormalCallback(std::shared_ptr<AudioHapticSoundNormalImpl> soundNormalImpl)
331     : soundNormalImpl_(soundNormalImpl) {}
332 
OnError(int32_t errorCode,const std::string & errorMsg)333 void AHSoundNormalCallback::OnError(int32_t errorCode, const std::string &errorMsg)
334 {
335     MEDIA_LOGE("OnError reported from AVPlayer: %{public}d", errorCode);
336     std::shared_ptr<AudioHapticSoundNormalImpl> soundNormalImpl = soundNormalImpl_.lock();
337     if (soundNormalImpl == nullptr) {
338         MEDIA_LOGE("The audio haptic player for normal mode has been released.");
339         return;
340     }
341     soundNormalImpl->NotifyErrorEvent(errorCode);
342 }
343 
OnInfo(Media::PlayerOnInfoType type,int32_t extra,const Media::Format & infoBody)344 void AHSoundNormalCallback::OnInfo(Media::PlayerOnInfoType type, int32_t extra, const Media::Format &infoBody)
345 {
346     if (type == INFO_TYPE_STATE_CHANGE) {
347         MEDIA_LOGI("OnInfo: state change reported from AVPlayer.");
348         HandleStateChangeEvent(extra, infoBody);
349     } else if (type == INFO_TYPE_INTERRUPT_EVENT) {
350         MEDIA_LOGI("OnInfo: interrupt event reported from AVPlayer.");
351         HandleAudioInterruptEvent(extra, infoBody);
352     } else if (type == INFO_TYPE_AUDIO_FIRST_FRAME) {
353         MEDIA_LOGI("OnInfo: first frame event reported from AVPlayer.");
354         HandleAudioFirstFrameEvent(extra, infoBody);
355     } else {
356         return;
357     }
358 }
359 
HandleStateChangeEvent(int32_t extra,const Format & infoBody)360 void AHSoundNormalCallback::HandleStateChangeEvent(int32_t extra, const Format &infoBody)
361 {
362     MEDIA_LOGI("HandleStateChangeEvent from AVPlayer");
363     PlayerStates avPlayerState = static_cast<PlayerStates>(extra);
364     switch (avPlayerState) {
365         case PLAYER_STATE_ERROR:
366             playerState_ = AudioHapticPlayerState::STATE_INVALID;
367             break;
368         case PLAYER_IDLE:
369         case PLAYER_INITIALIZED:
370         case PLAYER_PREPARING:
371             playerState_ = AudioHapticPlayerState::STATE_NEW;
372             break;
373         case PLAYER_PREPARED:
374             playerState_ = AudioHapticPlayerState::STATE_PREPARED;
375             break;
376         case PLAYER_STARTED:
377             playerState_ = AudioHapticPlayerState::STATE_RUNNING;
378             break;
379         case PLAYER_PAUSED:
380             playerState_ = AudioHapticPlayerState::STATE_PAUSED;
381             break;
382         case PLAYER_STOPPED:
383         case PLAYER_PLAYBACK_COMPLETE:
384             playerState_ = AudioHapticPlayerState::STATE_STOPPED;
385             break;
386         default:
387             break;
388     }
389     std::shared_ptr<AudioHapticSoundNormalImpl> soundNormalImpl = soundNormalImpl_.lock();
390     if (soundNormalImpl == nullptr) {
391         MEDIA_LOGE("The audio haptic player for normal mode has been released.");
392         return;
393     }
394     soundNormalImpl->SetAVPlayerState(playerState_);
395 
396     if (avPlayerState == PLAYER_PREPARED) {
397         soundNormalImpl->NotifyPreparedEvent();
398     } else if (avPlayerState == PLAYER_PLAYBACK_COMPLETE) {
399         soundNormalImpl->NotifyEndOfStreamEvent();
400     }
401 }
402 
HandleAudioInterruptEvent(int32_t extra,const Format & infoBody)403 void AHSoundNormalCallback::HandleAudioInterruptEvent(int32_t extra, const Format &infoBody)
404 {
405     MEDIA_LOGI("HandleAudioInterruptEvent from AVPlayer");
406     AudioStandard::InterruptEvent interruptEvent;
407     int32_t eventTypeValue = 0;
408     int32_t forceTypeValue = 0;
409     int32_t hintTypeValue = 0;
410     (void)infoBody.GetIntValue(PlayerKeys::AUDIO_INTERRUPT_TYPE, eventTypeValue);
411     (void)infoBody.GetIntValue(PlayerKeys::AUDIO_INTERRUPT_FORCE, forceTypeValue);
412     (void)infoBody.GetIntValue(PlayerKeys::AUDIO_INTERRUPT_HINT, hintTypeValue);
413     interruptEvent.eventType = static_cast<AudioStandard::InterruptType>(eventTypeValue);
414     interruptEvent.forceType = static_cast<AudioStandard::InterruptForceType>(forceTypeValue);
415     interruptEvent.hintType = static_cast<AudioStandard::InterruptHint>(hintTypeValue);
416 
417     std::shared_ptr<AudioHapticSoundNormalImpl> soundNormalImpl = soundNormalImpl_.lock();
418     if (soundNormalImpl == nullptr) {
419         MEDIA_LOGE("The audio haptic player for normal mode has been released.");
420         return;
421     }
422     soundNormalImpl->NotifyInterruptEvent(interruptEvent);
423 }
424 
HandleAudioFirstFrameEvent(int32_t extra,const Format & infoBody)425 void AHSoundNormalCallback::HandleAudioFirstFrameEvent(int32_t extra, const Format &infoBody)
426 {
427     int64_t value = 0;
428     (void)infoBody.GetLongValue(PlayerKeys::AUDIO_FIRST_FRAME, value);
429     uint64_t latency = static_cast<uint64_t>(value);
430     MEDIA_LOGI("HandleAudioFirstFrameEvent from AVPlayer. Latency %{public}" PRIu64 "", latency);
431     std::shared_ptr<AudioHapticSoundNormalImpl> soundNormalImpl = soundNormalImpl_.lock();
432     if (soundNormalImpl == nullptr) {
433         MEDIA_LOGE("The audio haptic player for normal mode has been released.");
434         return;
435     }
436     soundNormalImpl->NotifyFirstFrameEvent(latency);
437 }
438 } // namesapce AudioStandard
439 } // namespace OHOS