otter: vibrator: Update for 15
Update from vendor/qcom/opensource/vibrator
at commit 8f873decb09e5b4c2edf3ab1e1bad14764d943db
Change-Id: I12e0982fc051834628b00da14dde7a5c1c687e53
diff --git a/vibrator/Vibrator.cpp b/vibrator/Vibrator.cpp
index 06d26e0..abecdc9 100644
--- a/vibrator/Vibrator.cpp
+++ b/vibrator/Vibrator.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -28,7 +27,7 @@
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Changes from Qualcomm Innovation Center are provided under the following license:
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause-Clear
*/
@@ -77,6 +76,7 @@
#define MSM_CPU_TARO 457
#define MSM_CPU_TARO_LTE 552
#define MSM_CPU_KALAMA 519
+#define MSM_CPU_PINEAPPLE 557
#define test_bit(bit, array) ((array)[(bit)/8] & (1<<((bit)%8)))
@@ -141,7 +141,8 @@
&& strcmp(name, "aw8624_haptic")
&& strcmp(name, "aw8695_haptic")
&& strcmp(name, "aw8697_haptic")
- && strcmp(name, "awinic_haptic")) {
+ && strcmp(name, "awinic_haptic")
+ && strcmp(name, "drv2624:haptics")) {
ALOGD("not a supported haptics device\n");
close(fd);
continue;
@@ -179,6 +180,7 @@
case MSM_CPU_CAPE:
case APQ_CPU_CAPE:
case MSM_CPU_KALAMA:
+ case MSM_CPU_PINEAPPLE:
mSupportExternalControl = true;
break;
default:
@@ -221,10 +223,12 @@
const struct effect_stream *stream;
#endif
+ mtx.lock();
/* For QMAA compliance, return OK even if vibrator device doesn't exist */
if (mVibraFd == INVALID_VALUE) {
if (playLengthMs != NULL)
*playLengthMs = 0;
+ mtx.unlock();
return 0;
}
@@ -298,10 +302,12 @@
}
mCurrAppId = INVALID_VALUE;
}
+ mtx.unlock();
return 0;
errout:
mCurrAppId = INVALID_VALUE;
+ mtx.unlock();
return ret;
}
@@ -505,6 +511,8 @@
close(pipefd[1]);
}
+static int getPrimitiveDurationFromSysfs(uint32_t primitive_id, int32_t* durationMs);
+
ndk::ScopedAStatus Vibrator::getCapabilities(int32_t* _aidl_return) {
*_aidl_return = IVibrator::CAP_ON_CALLBACK;
@@ -516,10 +524,12 @@
if (ff.mSupportGain)
*_aidl_return |= IVibrator::CAP_AMPLITUDE_CONTROL;
if (ff.mSupportEffects) {
- *_aidl_return |= IVibrator::CAP_PERFORM_CALLBACK;
- if (access("/sys/class/qcom-haptics/primitive_duration", F_OK) == 0) {
+ *_aidl_return |= IVibrator::CAP_PERFORM_CALLBACK;
+ int32_t primitiveDuration = 0;
+ uint32_t primitiveId = static_cast<uint32_t>(CompositePrimitive::CLICK);
+ getPrimitiveDurationFromSysfs(primitiveId, &primitiveDuration);
+ if (primitiveDuration != 0)
*_aidl_return |= IVibrator::CAP_COMPOSE_EFFECTS;
- }
}
if (ff.mSupportExternalControl)
*_aidl_return |= IVibrator::CAP_EXTERNAL_CONTROL;
@@ -821,8 +831,32 @@
ALOGE("Failed to read stop status from pipe(playLengthMs), status = %d", status);
break;
}
- if (status == STOP_COMPOSE)
+ if (status == STOP_COMPOSE) {
+
+ /*
+ * There is a corner case that the off() command could be executed in
+ * main thread before the primitive play is triggered in the child thread,
+ * such as, when playing a very short primitive effect while the system is
+ * pretty busy (one example is enabling all kernel console log after executed
+ * "echo Y > /sys/module/printk/parameters/ignore_loglevel"), the child thread
+ * may not be able to schedule out for running before the main thread times out
+ * on the primitive duration and sent the off() command, there won't be any
+ * off() command coming again to stop the primitive effect after it's triggered.
+ *
+ * However, the primitive could be played out and stopped automatically but the
+ * haptics driver does expect an explicit off() command to restore HW/SW logic
+ * after that, so call it here. It would result a redundant off() command in
+ * normal case but it won't do any harm because it would be ignored and not sent
+ * to haptics driver because of an invalid mCurrAppId. It would also result in the
+ * primitive effect to stop immediately right after it's triggered in such
+ * corner case. But considering the main thread has stopped it before off() is
+ * called here, take this as a limitation and it is expected not playing the
+ * vibration out.
+ */
+
+ vibrator->ff.off();
break;
+ }
}
}
@@ -877,15 +911,17 @@
ALOGE("wait for last composePlayThread done timeout");
return ndk::ScopedAStatus::fromExceptionCode(EX_SERVICE_SPECIFIC);
}
+ }
- /* Read the pipe again to remove any stale data before triggering a new play */
- nfd = epoll_wait(epollfd, &events, 1, 0);
- if (nfd == -1 && (errno != EINTR)) {
- ALOGE("Failed to wait sleep playLengthMs, error=%d", errno);
- return ndk::ScopedAStatus::fromExceptionCode(EX_SERVICE_SPECIFIC);
- }
- if (nfd > 0)
- read(pipefd[0], &status, sizeof(int));
+ /* Read the pipe again to remove any stale data before triggering a new play */
+ nfd = epoll_wait(epollfd, &events, 1, 0);
+ if (nfd == -1 && (errno != EINTR)) {
+ ALOGE("Failed to wait sleep playLengthMs, error=%d", errno);
+ return ndk::ScopedAStatus::fromExceptionCode(EX_SERVICE_SPECIFIC);
+ }
+ if (nfd > 0) {
+ ALOGD("A stale event is cached in the pipe, remove it");
+ read(pipefd[0], &status, sizeof(int));
}
inComposition = true;