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