• 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 "audio_haptic_player_impl.h"
17 #include "audio_haptic_vibrator_impl.h"
18 
19 #include <fcntl.h>
20 #include <sys/stat.h>
21 #include <thread>
22 
23 #include "access_token.h"
24 #include "accesstoken_kit.h"
25 #include "ipc_skeleton.h"
26 #include "tokenid_kit.h"
27 
28 #include "audio_haptic_log.h"
29 #include "directory_ex.h"
30 #include "media_errors.h"
31 
32 namespace {
33 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_AUDIO_NAPI, "AudioHapticVibratorImpl"};
34 #ifdef SUPPORT_VIBRATOR
35 constexpr int32_t MIN_WAITING_TIME_FOR_VIBRATOR = 1200; // ms
36 constexpr uint64_t MILLISECONDS_FOR_ONE_SECOND = 1000; // ms
37 constexpr int32_t PLAYER_BUFFER_TIME = 30; // ms
38 constexpr int32_t PATTERN_DEFAULT_COUNT = 10;
39 constexpr int32_t PATTERN_MAX_COUNT = 200;
40 constexpr int32_t WAIT_VIBRATOR_CANCEL_TIME_MS = 50; // ms
41 constexpr float SIXTY_PERCENT = 0.6f;
42 constexpr int32_t HALF = 2;
43 constexpr int32_t DURATION_AT_LEAST = 100; // ms
44 constexpr int32_t NUM_ZERO = 0;
45 constexpr int32_t NUM_ONE = 0;
46 constexpr int32_t NUM_TWO = 0;
47 constexpr int32_t NUM_THREE = 0;
48 constexpr int32_t PATTERNDURATION_TIME_MS = 800; //ms
49 
CopyEvent(const VibratorEvent & strongEvent,VibratorEvent & weakEvent)50 void CopyEvent(const VibratorEvent &strongEvent, VibratorEvent &weakEvent)
51 {
52     // Copy event type
53     weakEvent.type = strongEvent.type;
54     // Copy event time
55     weakEvent.time = strongEvent.time;
56     // Copy event frequency
57     weakEvent.frequency = strongEvent.frequency;
58     // Copy event index
59     weakEvent.index = strongEvent.index;
60     // Modify intensity to 60% of the original and round to the nearest integer
61     weakEvent.intensity = static_cast<int32_t>(std::round(strongEvent.intensity * SIXTY_PERCENT));
62 
63     if (weakEvent.type == EVENT_TYPE_CONTINUOUS) {
64         // Modify duration to 50% of the original, but not less than 50ms
65         weakEvent.duration = std::max(50, strongEvent.duration / HALF);
66 
67         // Handle pointNum and points
68         if (strongEvent.pointNum != 0) {
69             // Set new pointNum to 4
70             weakEvent.pointNum = 4;
71 
72             // Allocate new points array
73             weakEvent.points = new VibratorCurvePoint[weakEvent.pointNum];
74 
75             // Set four points based on duration
76             int32_t duration = weakEvent.duration;
77             weakEvent.points[NUM_ZERO] = { 0, 100, 0 };
78             weakEvent.points[NUM_ONE] = { 1, 100, 0 };
79             weakEvent.points[NUM_TWO] = { duration -1, 100, 0 };
80             weakEvent.points[NUM_THREE] = { duration, 0, 0 };
81         }
82     }
83 }
84 
CopyPattern(const VibratorPattern & strongPattern,VibratorPattern & weakPattern)85 void CopyPattern(const VibratorPattern &strongPattern, VibratorPattern &weakPattern)
86 {
87     // Copy pattern basic properties
88     weakPattern.time = strongPattern.time;
89     weakPattern.eventNum = strongPattern.eventNum;
90     weakPattern.patternDuration = strongPattern.patternDuration;
91 
92     // Allocate and copy events array
93     if (strongPattern.eventNum > 0 && strongPattern.events != nullptr) {
94         weakPattern.events = new VibratorEvent[strongPattern.eventNum];
95 
96         for (int32_t i = 0; i < strongPattern.eventNum; ++i) {
97             CopyEvent(strongPattern.events[i], weakPattern.events[i]);
98         }
99     }
100 }
101 
convertToWeakVibratorPackage(const std::shared_ptr<VibratorPackage> & strongPackage,std::shared_ptr<VibratorPackage> & weakPackage)102 void convertToWeakVibratorPackage(const std::shared_ptr<VibratorPackage> &strongPackage,
103                                   std::shared_ptr<VibratorPackage> &weakPackage)
104 {
105     if (strongPackage == nullptr || weakPackage == nullptr) {
106         return;
107     }
108 
109     // Copy basic properties
110     weakPackage->patternNum = strongPackage->patternNum;
111     weakPackage->packageDuration = strongPackage->packageDuration;
112 
113     // Allocate and copy patterns array
114     if (strongPackage->patternNum > 0 && strongPackage->patterns != nullptr) {
115         weakPackage->patterns = new VibratorPattern[strongPackage->patternNum];
116 
117         // Handle each pattern
118         for (int32_t i = 0; i < strongPackage->patternNum; ++i) {
119             CopyPattern(strongPackage->patterns[i], weakPackage->patterns[i]);
120         }
121     }
122 }
123 #endif
124 
GetCurrentTimeMillis()125 int64_t GetCurrentTimeMillis()
126 {
127     return static_cast<uint64_t>(
128         std::chrono::duration_cast<std::chrono::milliseconds>(
129             std::chrono::system_clock::now().time_since_epoch()
130         ).count()
131     );
132 }
133 }
134 
135 namespace OHOS {
136 namespace Media {
137 #ifdef SUPPORT_VIBRATOR
138 static const std::unordered_map<AudioStandard::StreamUsage, VibratorUsage> USAGE_MAP = {
139     {AudioStandard::StreamUsage::STREAM_USAGE_MEDIA, VibratorUsage::USAGE_MEDIA},
140     {AudioStandard::StreamUsage::STREAM_USAGE_MUSIC, VibratorUsage::USAGE_MEDIA},
141     {AudioStandard::StreamUsage::STREAM_USAGE_VOICE_COMMUNICATION, VibratorUsage::USAGE_COMMUNICATION},
142     {AudioStandard::StreamUsage::STREAM_USAGE_VOICE_ASSISTANT, VibratorUsage::USAGE_MEDIA},
143     {AudioStandard::StreamUsage::STREAM_USAGE_ALARM, VibratorUsage::USAGE_ALARM},
144     {AudioStandard::StreamUsage::STREAM_USAGE_VOICE_MESSAGE, VibratorUsage::USAGE_COMMUNICATION},
145     {AudioStandard::StreamUsage::STREAM_USAGE_NOTIFICATION_RINGTONE, VibratorUsage::USAGE_RING},
146     {AudioStandard::StreamUsage::STREAM_USAGE_RINGTONE, VibratorUsage::USAGE_RING},
147     {AudioStandard::StreamUsage::STREAM_USAGE_VOICE_RINGTONE, VibratorUsage::USAGE_RING},
148     {AudioStandard::StreamUsage::STREAM_USAGE_NOTIFICATION, VibratorUsage::USAGE_NOTIFICATION},
149     {AudioStandard::StreamUsage::STREAM_USAGE_ACCESSIBILITY, VibratorUsage::USAGE_MEDIA},
150     {AudioStandard::StreamUsage::STREAM_USAGE_SYSTEM, VibratorUsage::USAGE_NOTIFICATION},
151     {AudioStandard::StreamUsage::STREAM_USAGE_MOVIE, VibratorUsage::USAGE_MEDIA},
152     {AudioStandard::StreamUsage::STREAM_USAGE_GAME, VibratorUsage::USAGE_MEDIA},
153     {AudioStandard::StreamUsage::STREAM_USAGE_AUDIOBOOK, VibratorUsage::USAGE_MEDIA},
154     {AudioStandard::StreamUsage::STREAM_USAGE_NAVIGATION, VibratorUsage::USAGE_MEDIA},
155     {AudioStandard::StreamUsage::STREAM_USAGE_DTMF, VibratorUsage::USAGE_NOTIFICATION},
156     {AudioStandard::StreamUsage::STREAM_USAGE_ENFORCED_TONE, VibratorUsage::USAGE_NOTIFICATION},
157     {AudioStandard::StreamUsage::STREAM_USAGE_ULTRASONIC, VibratorUsage::USAGE_MEDIA},
158     {AudioStandard::StreamUsage::STREAM_USAGE_VIDEO_COMMUNICATION, VibratorUsage::USAGE_COMMUNICATION},
159 };
160 #endif
161 const int ERROR = -1;
162 
IsSelfSystemCaller()163 bool IsSelfSystemCaller()
164 {
165     Security::AccessToken::FullTokenID selfTokenID = IPCSkeleton::GetSelfTokenID();
166     return Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(selfTokenID);
167 }
168 
AudioHapticVibratorImpl(AudioHapticPlayer & audioHapticPlayer)169 AudioHapticVibratorImpl::AudioHapticVibratorImpl(AudioHapticPlayer &audioHapticPlayer)
170     : audioHapticPlayer_(audioHapticPlayer)
171 {
172     if (audioHapticPlayer_.IsMuted(AUDIO_HAPTIC_TYPE_HAPTIC)) {
173         MEDIA_LOGW("The muteHaptic value of audioHapticPlayer_ is true. No need to vibrate.");
174     }
175 }
176 
~AudioHapticVibratorImpl()177 AudioHapticVibratorImpl::~AudioHapticVibratorImpl() {}
178 
179 std::mutex AudioHapticVibrator::createVibratorMutex_;
180 
CreateAudioHapticVibrator(AudioHapticPlayer & audioHapticPlayer)181 std::shared_ptr<AudioHapticVibrator> AudioHapticVibrator::CreateAudioHapticVibrator(
182     AudioHapticPlayer &audioHapticPlayer)
183 {
184     std::lock_guard<std::mutex> lock(createVibratorMutex_);
185     auto audioHapticVibrator = std::make_shared<AudioHapticVibratorImpl>(audioHapticPlayer);
186     return audioHapticVibrator;
187 }
188 
SetIsSupportEffectId(bool isSupport)189 void AudioHapticVibratorImpl::SetIsSupportEffectId(bool isSupport)
190 {
191 #ifdef SUPPORT_VIBRATOR
192     isSupportEffectId_ = isSupport;
193 #endif
194 }
195 
ExtractFd(const std::string & hapticsUri)196 int32_t AudioHapticVibratorImpl::ExtractFd(const std::string& hapticsUri)
197 {
198     const std::string prefix = "fd://";
199     if (hapticsUri.size() <= prefix.size() || hapticsUri.substr(0, prefix.length()) != prefix) {
200         MEDIA_LOGW("ExtractFd: Input does not start with the required prefix.");
201         return ERROR;
202     }
203 
204     std::string numberPart = hapticsUri.substr(prefix.length());
205     for (char c : numberPart) {
206         if (!std::isdigit(c)) {
207             MEDIA_LOGE("ExtractFd: The part after the prefix is not all digits.");
208             return ERROR;
209         }
210     }
211 
212     int32_t fd = atoi(numberPart.c_str());
213     return fd > FILE_DESCRIPTOR_INVALID ? fd : ERROR;
214 }
215 
OpenHapticSource(const HapticSource & hapticSource,int32_t & fd)216 int32_t AudioHapticVibratorImpl::OpenHapticSource(const HapticSource& hapticSource, int32_t& fd)
217 {
218 #ifdef SUPPORT_VIBRATOR
219     std::string hapticUri = hapticSource.hapticUri;
220     int32_t hapticFd = hapticSource.fd;
221     MEDIA_LOGI("OpenHapticSource. hapticUri [%{public}s], hapticFd [%{public}d]",
222         hapticUri.c_str(), hapticFd);
223     CHECK_AND_RETURN_RET_LOG(!hapticUri.empty() || hapticFd > FILE_DESCRIPTOR_INVALID, MSERR_OPEN_FILE_FAILED,
224         "hapticUri is empty or invalid hapticFd.");
225 
226     if (!hapticUri.empty()) {
227         int32_t oldFd = ExtractFd(hapticUri);
228         if (oldFd != ERROR) {
229             fd = dup(oldFd);
230         } else {
231             MEDIA_LOGW("OpenHapticFile: hapticUri is not new format.");
232 
233             std::string absFilePath;
234             if (!PathToRealPath(hapticUri, absFilePath)) {
235                 MEDIA_LOGE("file is not real path, file path: %{private}s", hapticUri.c_str());
236                 return ERROR;
237             }
238             if (absFilePath.empty()) {
239                 MEDIA_LOGE("Failed to obtain the canonical path for source path %{public}d %{private}s",
240                     errno, hapticUri.c_str());
241                 return ERROR;
242             }
243 
244             fd = open(hapticUri.c_str(), O_RDONLY | O_CLOEXEC);
245         }
246     } else {
247         fd = dup(hapticFd);
248     }
249 
250     CHECK_AND_RETURN_RET_LOG(fd > FILE_DESCRIPTOR_INVALID, MSERR_OPEN_FILE_FAILED,
251         "OpenHapticSource: open source failed, file path: %{public}s, fd: %{public}d", hapticUri.c_str(), hapticFd);
252 #endif
253     return MSERR_OK;
254 }
255 
OpenHapticFile(const HapticSource & hapticSource)256 int32_t AudioHapticVibratorImpl::OpenHapticFile(const HapticSource& hapticSource)
257 {
258 #ifdef SUPPORT_VIBRATOR
259     int32_t newFd = FILE_DESCRIPTOR_INVALID;
260     int32_t ret = OpenHapticSource(hapticSource, newFd);
261     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "OpenHapticFile: open file failed");
262 
263     vibratorFD_ = std::make_shared<VibratorFileDescription>();
264     CHECK_AND_RETURN_RET_LOG(vibratorFD_ != nullptr, ERROR, "vibratorFD_ is null");
265     vibratorPkg_ = std::make_shared<VibratorPackage>();
266     CHECK_AND_RETURN_RET_LOG(vibratorPkg_ != nullptr, ERROR, "vibratorPkg_ is null");
267 
268     struct stat64 statbuf = { 0 };
269     if (fstat64(newFd, &statbuf) == 0) {
270         vibratorFD_->fd = newFd;
271         vibratorFD_->offset = hapticSource.offset;
272         vibratorFD_->length = hapticSource.length > 0 ? hapticSource.length : statbuf.st_size;
273         return MSERR_OK;
274     } else {
275         close(newFd);
276         return MSERR_OPEN_FILE_FAILED;
277     }
278 #endif
279     return MSERR_OK;
280 }
281 
PreLoad(const HapticSource & hapticSource,const AudioStandard::StreamUsage & streamUsage)282 int32_t AudioHapticVibratorImpl::PreLoad(const HapticSource &hapticSource,
283     const AudioStandard::StreamUsage &streamUsage)
284 {
285     MEDIA_LOGI("PreLoad with hapticUri [%{public}s], effectId [%{public}s], streamUsage [%{public}d]",
286         hapticSource.hapticUri.c_str(), hapticSource.effectId.c_str(), streamUsage);
287     streamUsage_ = streamUsage;
288 #ifdef SUPPORT_VIBRATOR
289     if (audioHapticPlayer_.GetHapticsMode() == HapticsMode::HAPTICS_MODE_NONE) {
290         MEDIA_LOGI("The hapticdMopde value of audioHapticPlayer_ is NONE. No need to vibrate.");
291         return MSERR_OK;
292     }
293     auto iterator = USAGE_MAP.find(streamUsage_);
294     if (iterator != USAGE_MAP.end()) {
295         vibratorUsage_ = iterator->second;
296     } else {
297         MEDIA_LOGW("Invalid stream usage! Use the default usage (USAGE_MEDIA).");
298         vibratorUsage_ = VibratorUsage::USAGE_MEDIA;
299     }
300     hapticSource_ = hapticSource;
301     if (hapticSource.hapticUri == "" && hapticSource.fd == FILE_DESCRIPTOR_INVALID) {
302         bool isSupported = false;
303         int32_t effectResult = Sensors::IsSupportEffect(hapticSource.effectId.c_str(), &isSupported);
304         if (effectResult == 0 && isSupported) {
305             SetIsSupportEffectId(true);
306             MEDIA_LOGI("The effectId is supported. Vibrator has been prepared.");
307             return MSERR_OK;
308         } else {
309             MEDIA_LOGE("The effectId is not supported!");
310             return MSERR_UNSUPPORT_FILE;
311         }
312     }
313 
314     if (OpenHapticFile(hapticSource) != MSERR_OK) {
315         return MSERR_OPEN_FILE_FAILED;
316     }
317 
318     int32_t result = Sensors::PreProcess(*vibratorFD_, *vibratorPkg_);
319     if (result != 0) {
320         return MSERR_UNSUPPORT_FILE;
321     }
322     close(vibratorFD_->fd);
323 #endif
324     return MSERR_OK;
325 }
326 
SetHapticIntensity(float intensity)327 int32_t AudioHapticVibratorImpl::SetHapticIntensity(float intensity)
328 {
329     MEDIA_LOGI("SetHapticIntensity for effectId source. intensity: %{public}f", intensity);
330     std::lock_guard<std::mutex> lock(vibrateMutex_);
331     int32_t result = MSERR_OK;
332 #ifdef SUPPORT_VIBRATOR
333     if (hapticSource_.hapticUri == "" && hapticSource_.fd == FILE_DESCRIPTOR_INVALID) {
334         vibrateIntensity_ = intensity;
335     } else {
336         if (isRunning_) {
337             if (isIntensityChanged_) {
338                 result = ERR_OPERATE_NOT_ALLOWED;
339             } else {
340                 result = SeekAndRestart();
341             }
342         }
343         CHECK_AND_RETURN_RET_LOG(result == MSERR_OK, result,
344             "AudioHapticVibratorImpl::SetHapticIntensity failed. result: %{public}d", result);
345         vibratorParameter_.intensity = intensity;
346     }
347 #endif
348     return result;
349 }
350 
SetHapticsFeature(const HapticsFeature & feature)351 int32_t AudioHapticVibratorImpl::SetHapticsFeature(const HapticsFeature &feature)
352 {
353     MEDIA_LOGI("AudioHapticVibratorImpl::SetHapticsFeature %{public}d", feature);
354     std::lock_guard<std::mutex> lock(vibrateMutex_);
355     int32_t result = MSERR_OK;
356 #ifdef SUPPORT_VIBRATOR
357     if (vibratorPkg_ == nullptr) {
358         return ERR_OPERATE_NOT_ALLOWED;
359     }
360     if (feature == HapticsFeature::GENTLE_HAPTICS) {
361         auto gentlePkg = std::make_shared<VibratorPackage>();
362         convertToWeakVibratorPackage(vibratorPkg_, gentlePkg);
363         std::swap(vibratorPkg_, gentlePkg);
364 
365         if (isRunning_) {
366             result = SeekAndRestart();
367         }
368 
369         if (gentlePkg != nullptr) {
370             Sensors::FreeVibratorPackage(*gentlePkg);
371             gentlePkg = nullptr;
372         }
373     }
374 #endif
375     return result;
376 }
377 
SetHapticsRamp(int32_t duration,float startIntensity,float endIntensity)378 int32_t AudioHapticVibratorImpl::SetHapticsRamp(int32_t duration, float startIntensity, float endIntensity)
379 {
380     MEDIA_LOGI("AudioHapticVibratorImpl::SetHapticsRamp %{public}d, %{public}f, %{public}f",
381         duration, startIntensity, endIntensity);
382     std::lock_guard<std::mutex> lock(vibrateMutex_);
383     int32_t result = MSERR_OK;
384 #ifdef SUPPORT_VIBRATOR
385     if (isRunning_.load() || vibratorPkg_ == nullptr) {
386         return ERR_OPERATE_NOT_ALLOWED;
387     }
388     // duration not less than 100ms and not larger than haptics package duration
389     auto lastPattern = vibratorPkg_->patterns[vibratorPkg_->patternNum - 1];
390     auto packageDuration = lastPattern.time + lastPattern.patternDuration;
391     int32_t actualDuration = duration;
392     if (duration > packageDuration) {
393         actualDuration = packageDuration;
394     }
395     if (actualDuration < DURATION_AT_LEAST) {
396         MEDIA_LOGE("AudioHapticVibratorImpl::SetHapticsRamp error, duration %{public}d, packageDuration %{public}d",
397             actualDuration, packageDuration);
398         return MSERR_INVALID_VAL;
399     }
400 
401     if (startIntensity < 1.0f || startIntensity > 100.0f) {
402         MEDIA_LOGE("AudioHapticVibratorImpl::SetHapticsRamp: the startIntensity value is invalid.");
403         return MSERR_INVALID_VAL;
404     }
405 
406     if (endIntensity < 1.0f || endIntensity > 100.0f) {
407         MEDIA_LOGE("AudioHapticVibratorImpl::SetHapticsRamp: the endIntensity value is invalid.");
408         return MSERR_INVALID_VAL;
409     }
410 
411     // four points will be enough
412     int32_t numPoints = 4;
413     VibratorCurvePoint points[numPoints];
414     int32_t timeInterval = actualDuration / numPoints;
415     int32_t intensityStep = (endIntensity - startIntensity) / numPoints;
416 
417     for (int i = 0; i < numPoints; ++i) {
418         points[i].time = i * timeInterval;
419         points[i].intensity = startIntensity + i * intensityStep;
420     }
421     modulatePkg_ = std::make_shared<VibratorPackage>();
422     result = Sensors::ModulatePackage(points, numPoints, packageDuration, *vibratorPkg_, *modulatePkg_);
423     if (result == MSERR_OK) {
424         std::swap(vibratorPkg_, modulatePkg_);
425         rampEndIntensity_ = endIntensity;
426     }
427 #endif
428     return result;
429 }
430 
Release()431 int32_t AudioHapticVibratorImpl::Release()
432 {
433     std::lock_guard<std::mutex> lock(vibrateMutex_);
434     isStopped_ = true;
435 #ifdef SUPPORT_VIBRATOR
436     int32_t result = Sensors::Cancel();
437     if (result != 0) {
438         MEDIA_LOGE("Failed to stop vibrator: result %{public}d", result);
439     }
440     vibrateCV_.notify_one();
441 
442     if (vibratorPkg_ != nullptr) {
443         Sensors::FreeVibratorPackage(*vibratorPkg_);
444         vibratorPkg_ = nullptr;
445     }
446     if (seekVibratorPkg_ != nullptr) {
447         Sensors::FreeVibratorPackage(*seekVibratorPkg_);
448         seekVibratorPkg_ = nullptr;
449     }
450     if (modulatePkg_ != nullptr) {
451         Sensors::FreeVibratorPackage(*modulatePkg_);
452         modulatePkg_ = nullptr;
453     }
454     vibratorFD_ = nullptr;
455 
456 #endif
457     return MSERR_OK;
458 }
459 
ResetStopState()460 void AudioHapticVibratorImpl::ResetStopState()
461 {
462     std::lock_guard<std::mutex> lock(vibrateMutex_);
463     isStopped_ = false;
464 }
465 
StartVibrate(const AudioLatencyMode & latencyMode)466 int32_t AudioHapticVibratorImpl::StartVibrate(const AudioLatencyMode &latencyMode)
467 {
468     MEDIA_LOGI("StartVibrate: for latency mode %{public}d", latencyMode);
469     int32_t result = MSERR_OK;
470 #ifdef SUPPORT_VIBRATOR
471     vibrationTimeElapsed_ = 0;
472     patternStartTime_ = GetCurrentTimeMillis();
473     vibratorTime_.store(0);
474     if (audioHapticPlayer_.GetHapticsMode() == HapticsMode::HAPTICS_MODE_NONE) {
475         return result;
476     } else if (audioHapticPlayer_.GetHapticsMode() == HapticsMode::HAPTICS_MODE_NON_SYNC) {
477         return StartNonSyncVibration();
478     } else if (audioHapticPlayer_.GetHapticsMode() == HapticsMode::HAPTICS_MODE_NON_SYNC_ONCE) {
479         return StartNonSyncOnceVibration();
480     }
481     if (latencyMode == AUDIO_LATENCY_MODE_NORMAL) {
482         return StartVibrateForAVPlayer();
483     } else if (latencyMode == AUDIO_LATENCY_MODE_FAST) {
484         if (isSupportEffectId_) {
485             return StartVibrateWithEffect();
486         } else {
487             return StartVibrateForSoundPool();
488         }
489     } else {
490         return MSERR_INVALID_OPERATION;
491     }
492 #endif
493     return result;
494 }
495 
StartVibrateWithEffect()496 int32_t AudioHapticVibratorImpl::StartVibrateWithEffect()
497 {
498     int32_t result = MSERR_OK;
499 #ifdef SUPPORT_VIBRATOR
500     std::lock_guard<std::mutex> lock(vibrateMutex_);
501     (void)Sensors::SetUsage(vibratorUsage_, enableInSilentMode_.load());
502     MEDIA_LOGI("PlayPrimitiveEffect with effectId: %{public}s", hapticSource_.effectId.c_str());
503     result = Sensors::PlayPrimitiveEffect(hapticSource_.effectId.c_str(), vibrateIntensity_);
504     if (result != 0) {
505         MEDIA_LOGE("Failed to PlayPrimitiveEffect with effectId: %{public}s, result: %{public}d",
506             hapticSource_.effectId.c_str(), result);
507     }
508 #endif
509     return result;
510 }
511 
PlayVibrateForSoundPool(const std::shared_ptr<VibratorPackage> & vibratorPkg,std::unique_lock<std::mutex> & lock)512 int32_t AudioHapticVibratorImpl::PlayVibrateForSoundPool(
513     const std::shared_ptr<VibratorPackage>& vibratorPkg,
514     std::unique_lock<std::mutex>& lock
515 )
516 {
517     int32_t result = MSERR_OK;
518 #ifdef SUPPORT_VIBRATOR
519     // record the pattern time which has been played
520     int32_t vibrateTime = vibratorTime_.load();
521     for (int32_t i = 0; i < vibratorPkg->patternNum; ++i) {
522         result = PlayVibrationPattern(vibratorPkg, i, vibrateTime, lock);
523         CHECK_AND_RETURN_RET_LOG(result == 0, result, "AudioHapticVibratorImpl::PlayVibrateForSoundPool failed.");
524         if (isStopped_) {
525             return result;
526         }
527         if (isNeedRestart_) {
528             break;
529         }
530     }
531 
532     if (isNeedRestart_ && seekVibratorPkg_ != nullptr) {
533         isNeedRestart_ = false;
534         MEDIA_LOGI("AudioHapticVibratorImpl::PlayVibrateForSoundPool change intensity and restart.");
535         result = PlayVibrateForSoundPool(seekVibratorPkg_, lock);
536         if (Sensors::FreeVibratorPackage(*seekVibratorPkg_) == MSERR_OK) {
537             seekVibratorPkg_ = nullptr;
538         }
539     }
540 #endif
541     return result;
542 }
543 
ResumeModulePackge()544 void AudioHapticVibratorImpl::ResumeModulePackge()
545 {
546     if (modulatePkg_ != nullptr) {
547         std::swap(modulatePkg_, vibratorPkg_);
548         Sensors::FreeVibratorPackage(*modulatePkg_);
549         modulatePkg_ = nullptr;
550         vibratorParameter_.intensity = rampEndIntensity_;
551         rampEndIntensity_ = -1.0f;
552     }
553 }
554 
StartVibrateForSoundPool()555 int32_t AudioHapticVibratorImpl::StartVibrateForSoundPool()
556 {
557     std::unique_lock<std::mutex> lock(vibrateMutex_);
558     if (isStopped_) {
559         MEDIA_LOGW("Vibrator has been stopped. Return ok immediately");
560         AudioHapticPlayerImpl::SendHapticPlayerEvent(MSERR_OK, "VIBRATOR_STOP");
561         return MSERR_OK;
562     }
563 
564     int32_t result = MSERR_OK;
565 #ifdef SUPPORT_VIBRATOR
566     if (vibratorPkg_ == nullptr || vibratorFD_ == nullptr) {
567         MEDIA_LOGE("Vibration source file is not prepared. Can not start vibrating");
568         AudioHapticPlayerImpl::SendHapticPlayerEvent(MSERR_INVALID_OPERATION, "VIBRATOR_NOT_PREPARE");
569         return MSERR_INVALID_OPERATION;
570     }
571     isRunning_.store(true);
572     result = PlayVibrateForSoundPool(vibratorPkg_, lock);
573     ResumeModulePackge();
574     isRunning_.store(false);
575     isIntensityChanged_.store(false);
576 #endif
577     return result;
578 }
579 
RunVibrationPatterns(const std::shared_ptr<VibratorPackage> & vibratorPkg,std::unique_lock<std::mutex> & lock)580 int32_t AudioHapticVibratorImpl::RunVibrationPatterns(const std::shared_ptr<VibratorPackage>& vibratorPkg,
581                                                       std::unique_lock<std::mutex> &lock)
582 {
583     int32_t result = MSERR_OK;
584 #ifdef SUPPORT_VIBRATOR
585     // record the pattern time which has been played
586     int32_t vibrateTime = vibratorTime_.load();
587     for (int32_t i = 0; i < vibratorPkg->patternNum; ++i) {
588         result = PlayVibrationPattern(vibratorPkg, i, vibrateTime, lock);
589         CHECK_AND_RETURN_RET_LOG(result == 0, result, "AudioHapticVibratorImpl::PlayVibrateForSoundPool failed.");
590         if (isStopped_) {
591             return result;
592         }
593         if (isNeedRestart_) {
594             break;
595         }
596     }
597     if (isNeedRestart_ && seekVibratorPkg_ != nullptr) {
598         isNeedRestart_ = false;
599         MEDIA_LOGI("AudioHapticVibratorImpl::RunVibrationPatterns change intensity and restart.");
600         result = RunVibrationPatterns(seekVibratorPkg_, lock);
601         if (Sensors::FreeVibratorPackage(*seekVibratorPkg_) == MSERR_OK) {
602             seekVibratorPkg_ = nullptr;
603         }
604     }
605 #endif
606     return result;
607 }
608 
StartNonSyncVibration()609 int32_t AudioHapticVibratorImpl::StartNonSyncVibration()
610 {
611     std::unique_lock<std::mutex> lock(vibrateMutex_);
612     if (isStopped_) {
613         MEDIA_LOGW("Vibrator has been stopped. Return ok immediately");
614         return MSERR_OK;
615     }
616 
617     int32_t result = MSERR_OK;
618 #ifdef SUPPORT_VIBRATOR
619     if (vibratorPkg_ == nullptr || vibratorFD_ == nullptr) {
620         MEDIA_LOGE("Vibration source file is not prepared. Can not start vibrating");
621         return MSERR_INVALID_OPERATION;
622     }
623     isRunning_ = true;
624     while (!isStopped_) {
625         vibrationTimeElapsed_ = 0;
626         patternStartTime_ = GetCurrentTimeMillis();
627         result = RunVibrationPatterns(vibratorPkg_, lock);
628         ResumeModulePackge();
629         if (result != MSERR_OK) {
630             MEDIA_LOGI("StartNonSyncVibration: RunVibrationPatterns fail.");
631             return result;
632         }
633     }
634     isRunning_ = false;
635     isIntensityChanged_ = false;
636 #endif
637     return result;
638 }
639 
StartNonSyncOnceVibration()640 int32_t AudioHapticVibratorImpl::StartNonSyncOnceVibration()
641 {
642     std::unique_lock<std::mutex> lock(vibrateMutex_);
643     if (isStopped_) {
644         MEDIA_LOGW("Vibrator has been stopped. Return ok immediately");
645         return MSERR_OK;
646     }
647 
648     int32_t result = MSERR_OK;
649 #ifdef SUPPORT_VIBRATOR
650     if (vibratorPkg_ == nullptr || vibratorFD_ == nullptr) {
651         MEDIA_LOGE("Vibration source file is not prepared. Can not start vibrating");
652         return MSERR_INVALID_OPERATION;
653     }
654     isRunning_ = true;
655     result = RunVibrationPatterns(vibratorPkg_, lock);
656     ResumeModulePackge();
657     isRunning_ = false;
658     isIntensityChanged_ = false;
659     if (result != MSERR_OK) {
660         MEDIA_LOGI("StartNonSyncOnceVibration: RunVibrationPatterns fail.");
661         return result;
662     }
663 #endif
664     return result;
665 }
666 
PlayVibrationPattern(const std::shared_ptr<VibratorPackage> & vibratorPkg,int32_t patternIndex,int32_t & vibrateTime,std::unique_lock<std::mutex> & lock)667 int32_t AudioHapticVibratorImpl::PlayVibrationPattern(
668     const std::shared_ptr<VibratorPackage>& vibratorPkg,
669     int32_t patternIndex,
670     int32_t& vibrateTime,
671     std::unique_lock<std::mutex>& lock
672 )
673 {
674     int32_t result = MSERR_OK;
675 #ifdef SUPPORT_VIBRATOR
676     if (patternIndex > vibratorPkg->patternNum - 1) {
677         return result;
678     }
679 
680     // the delay time of first frame has been handled in audio haptic player
681     // calculate the time of single pattern
682     MEDIA_LOGI("AudioHapticVibratorImpl::PlayVibrationPattern pattern time %{public}d",
683         vibratorPkg->patterns[patternIndex].time);
684     int32_t patternTime = vibratorPkg->patterns[patternIndex].time - vibrateTime;
685     vibrateTime = vibratorPkg->patterns[patternIndex].time;
686 
687     (void)vibrateCV_.wait_for(lock, std::chrono::milliseconds(patternTime < 0 ? 0 : patternTime),
688         [this]() { return isStopped_ || isNeedRestart_; });
689     CHECK_AND_RETURN_RET_LOG(!isStopped_ && !isNeedRestart_, result,
690         "AudioHapticVibratorImpl::PlayVibrationPattern: Stop() is call when waiting");
691     (void)Sensors::SetUsage(vibratorUsage_, enableInSilentMode_.load());
692     (void)Sensors::SetParameters(vibratorParameter_);
693     MEDIA_LOGI("AudioHapticVibratorImpl::PlayVibrationPattern.");
694     patternStartTime_ = GetCurrentTimeMillis();
695     vibrationTimeElapsed_ = vibratorPkg->patterns[patternIndex].time;
696     if (audioHapticSyncId_ > 0 && !IsNonSync()) {
697         result = Sensors::PlayPatternBySessionId(audioHapticSyncId_, vibratorPkg->patterns[patternIndex]);
698     } else {
699         result = Sensors::PlayPattern(vibratorPkg->patterns[patternIndex]);
700     }
701     CHECK_AND_RETURN_RET_LOG(result == 0, result,
702         "AudioHapticVibratorImpl::PlayVibrationPattern: Failed to PlayPattern. Error %{public}d", result);
703 
704     // last pattern need to wait
705     if (patternIndex == vibratorPkg->patternNum - 1) {
706         int32_t lastPatternDuration = vibratorPkg->patterns[patternIndex].patternDuration + PATTERNDURATION_TIME_MS;
707         (void)vibrateCV_.wait_for(lock, std::chrono::milliseconds(lastPatternDuration),
708             [this]() { return isStopped_ || isNeedRestart_; });
709         CHECK_AND_RETURN_RET_LOG(!isStopped_ && !isNeedRestart_, result,
710             "AudioHapticVibratorImpl::PlayVibrationPattern: Stop() is call when waiting");
711     }
712 #endif
713     return result;
714 }
715 
PlayVibrateForAVPlayer(const std::shared_ptr<VibratorPackage> & vibratorPkg,std::unique_lock<std::mutex> & lock)716 int32_t AudioHapticVibratorImpl::PlayVibrateForAVPlayer(const std::shared_ptr<VibratorPackage>& vibratorPkg,
717                                                         std::unique_lock<std::mutex>& lock)
718 {
719     int32_t result = MSERR_OK;
720 #ifdef SUPPORT_VIBRATOR
721     // record the pattern time which has been played
722     int32_t vibrateTime = vibratorTime_.load();
723     MEDIA_LOGI("AudioHapticVibratorImpl::PlayVibrateForAVPlayer: now: %{public}d", vibrateTime);
724     int32_t patternDuration = IsSelfSystemCaller() ? PATTERN_MAX_COUNT : PATTERN_DEFAULT_COUNT;
725     for (int32_t i = 0; i < vibratorPkg->patternNum; ++i) {
726         result = PlayVibrationPattern(vibratorPkg, i, vibrateTime, lock);
727         AudioHapticPlayerImpl::SendHapticPlayerEvent(result, "PLAY_PATTERN_AVPLAYER");
728         CHECK_AND_RETURN_RET_LOG(result == 0, result, "AudioHapticVibratorImpl::PlayVibrateForAVPlayer failed.");
729         if (isStopped_) {
730             return result;
731         }
732         // get the audio time every second and handle the delay time unless DSP do sync work(syncId > 0)
733         if (isNeedRestart_ || i + 1 >= vibratorPkg->patternNum) {
734             break;
735         }
736         if (audioHapticSyncId_ > 0) {
737             continue;
738         }
739         int32_t nextVibratorTime = vibratorPkg->patterns[i + 1].time;
740         vibrateTime = audioHapticPlayer_.GetAudioCurrentTime() + PLAYER_BUFFER_TIME + GetDelayTime();
741         int32_t count = 0;
742         while (nextVibratorTime - vibrateTime > MIN_WAITING_TIME_FOR_VIBRATOR && count < patternDuration) {
743             (void)vibrateCV_.wait_for(lock, std::chrono::milliseconds(MILLISECONDS_FOR_ONE_SECOND),
744                 [this]() { return isStopped_ || isNeedRestart_; });
745             CHECK_AND_RETURN_RET_LOG(!isStopped_, result, "PlayVibrateForAVPlayer: Stop() is call when waiting");
746             if (isNeedRestart_) {
747                 break;
748             }
749             vibrateTime = audioHapticPlayer_.GetAudioCurrentTime() + PLAYER_BUFFER_TIME + GetDelayTime();
750             count++;
751         }
752         if (count == patternDuration) {
753             MEDIA_LOGE("PlayVibrateForAVPlayer: loop count has reached the max value.");
754             return MSERR_INVALID_OPERATION;
755         }
756     }
757     if (isNeedRestart_ && seekVibratorPkg_ != nullptr) {
758         isNeedRestart_ = false;
759         MEDIA_LOGI("AudioHapticVibratorImpl::PlayVibrateForAVPlayer change intensity and restart.");
760         result = PlayVibrateForAVPlayer(seekVibratorPkg_, lock);
761         if (Sensors::FreeVibratorPackage(*seekVibratorPkg_) == MSERR_OK) {
762             seekVibratorPkg_ = nullptr;
763         }
764     }
765 #endif
766     return result;
767 }
768 
StartVibrateForAVPlayer()769 int32_t AudioHapticVibratorImpl::StartVibrateForAVPlayer()
770 {
771     std::unique_lock<std::mutex> lock(vibrateMutex_);
772     if (isStopped_) {
773         MEDIA_LOGW("Vibrator has been stopped. Return ok immediately");
774         return MSERR_OK;
775     }
776 
777     int32_t result = MSERR_OK;
778 #ifdef SUPPORT_VIBRATOR
779     if (vibratorPkg_ == nullptr || vibratorFD_ == nullptr) {
780         MEDIA_LOGE("Vibration source file is not prepared. Can not start vibrating");
781         return MSERR_INVALID_OPERATION;
782     }
783     isRunning_.store(true);
784     result = PlayVibrateForAVPlayer(vibratorPkg_, lock);
785     ResumeModulePackge();
786     isRunning_.store(false);
787     isIntensityChanged_.store(false);
788 #endif
789     return result;
790 }
791 
SeekAndRestart()792 int32_t AudioHapticVibratorImpl::SeekAndRestart()
793 {
794     if (patternStartTime_ == 0) {
795         return MSERR_OK;
796     }
797 
798     seekVibratorPkg_ = std::make_shared<VibratorPackage>();
799     auto duration = GetCurrentTimeMillis() - patternStartTime_;
800     MEDIA_LOGI("AudioHapticVibratorImpl::SeekAndRestart vibrationTimeElapsed_: %{public}d duration: %{public}" PRId64,
801         vibrationTimeElapsed_.load(), duration);
802     int32_t result = Sensors::SeekTimeOnPackage(vibrationTimeElapsed_ + duration + WAIT_VIBRATOR_CANCEL_TIME_MS,
803         *vibratorPkg_, *seekVibratorPkg_);
804     CHECK_AND_RETURN_RET_LOG(result == MSERR_OK, result,
805         "AudioHapticVibratorImpl::SeekAndRestart SeekTimeOnPackage error");
806     isNeedRestart_ = true;
807     isIntensityChanged_ = true;
808     vibratorTime_.store(vibrationTimeElapsed_ + duration);
809     // cancel is async, so should wait for 50ms then restart
810     (void)Sensors::Cancel();
811     std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_VIBRATOR_CANCEL_TIME_MS));
812     vibrateCV_.notify_one();
813     return MSERR_OK;
814 }
815 
StopVibrate()816 int32_t AudioHapticVibratorImpl::StopVibrate()
817 {
818     std::lock_guard<std::mutex> lock(vibrateMutex_);
819     isStopped_ = true;
820     int32_t result = MSERR_OK;
821 #ifdef SUPPORT_VIBRATOR
822     vibrateCV_.notify_one();
823     result = Sensors::Cancel();
824     MEDIA_LOGI("StopVibrate: %{public}d", result);
825 #endif
826     return result;
827 }
828 
GetDelayTime()829 int32_t AudioHapticVibratorImpl::GetDelayTime()
830 {
831     int32_t delayTime = 0;
832 #ifdef SUPPORT_VIBRATOR
833     (void)Sensors::GetDelayTime(delayTime);
834 #endif
835     return delayTime;
836 }
837 
IsHapticsCustomSupported()838 bool AudioHapticVibratorImpl::IsHapticsCustomSupported()
839 {
840     std::lock_guard<std::mutex> lock(vibrateMutex_);
841     int32_t result = false;
842 #ifdef SUPPORT_VIBRATOR
843     result = Sensors::IsSupportVibratorCustom();
844     MEDIA_LOGI("AudioHapticVibratorImpl::IsHapticsCustomSupported: %{public}d", result);
845 #endif
846     return result;
847 }
848 
IsNonSync()849 bool AudioHapticVibratorImpl::IsNonSync()
850 {
851     return audioHapticPlayer_.GetHapticsMode() == HapticsMode::HAPTICS_MODE_NON_SYNC ||
852         audioHapticPlayer_.GetHapticsMode() == HapticsMode::HAPTICS_MODE_NON_SYNC_ONCE;
853 }
854 } // namesapce Media
855 } // namespace OHOS