diff --git a/audio/felix/config/audio_policy_configuration_a2dp_offload_disabled.xml b/audio/felix/config/audio_policy_configuration_a2dp_offload_disabled.xml index da6c7a7..5b97dd8 100644 --- a/audio/felix/config/audio_policy_configuration_a2dp_offload_disabled.xml +++ b/audio/felix/config/audio_policy_configuration_a2dp_offload_disabled.xml @@ -59,7 +59,7 @@ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> - diff --git a/audio/felix/config/audio_policy_configuration_bluetooth_legacy_hal.xml b/audio/felix/config/audio_policy_configuration_bluetooth_legacy_hal.xml index 416d4ab..fb54198 100644 --- a/audio/felix/config/audio_policy_configuration_bluetooth_legacy_hal.xml +++ b/audio/felix/config/audio_policy_configuration_bluetooth_legacy_hal.xml @@ -59,7 +59,7 @@ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> - - diff --git a/audio/felix/config/bluetooth_with_le_audio_policy_configuration_7_0.xml b/audio/felix/config/bluetooth_with_le_audio_policy_configuration_7_0.xml index 8b2af59..efd7277 100644 --- a/audio/felix/config/bluetooth_with_le_audio_policy_configuration_7_0.xml +++ b/audio/felix/config/bluetooth_with_le_audio_policy_configuration_7_0.xml @@ -11,6 +11,7 @@ channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> + + + sources="le audio output"/> + \ No newline at end of file diff --git a/conf/init.felix.rc b/conf/init.felix.rc index 47475e3..46a8980 100644 --- a/conf/init.felix.rc +++ b/conf/init.felix.rc @@ -86,7 +86,7 @@ on early-boot start insmod_sh_felix chown system system /sys/class/power_supply/dualbatt/dbatt_stats -service insmod_sh_felix /vendor/bin/insmod.sh /vendor/etc/init.insmod.felix.cfg +service insmod_sh_felix /vendor/bin/insmod.sh /vendor_dlkm/etc/init.insmod.felix.cfg class main user root group root system diff --git a/device-felix.mk b/device-felix.mk index a8f0192..1462ad5 100644 --- a/device-felix.mk +++ b/device-felix.mk @@ -41,8 +41,8 @@ $(call soong_config_set,fp_hal_feature,pixel_product, product_a) include device/google/felix/vibrator/cs40l26/device.mk include device/google/gs-common/bcmbt/bluetooth.mk include device/google/gs-common/display/dump_second_display.mk -include device/google/gs-common/touch/gti/gti.mk -include device/google/gs-common/touch/stm/stm6.mk +include device/google/gs-common/touch/gti/predump_gti_dual.mk +include device/google/gs-common/touch/stm/predump_stm6.mk ifeq ($(filter factory_felix, $(TARGET_PRODUCT)),) include device/google/felix/uwb/uwb_calibration.mk endif @@ -60,9 +60,13 @@ PRODUCT_COPY_FILES += \ PRODUCT_COPY_FILES += \ device/google/felix/conf/init.recovery.device.rc:$(TARGET_COPY_OUT_RECOVERY)/root/init.recovery.felix.rc -# insmod files +# insmod files. Kernel 5.10 prebuilts don't provide these yet, so provide our +# own copy if they're not in the prebuilts. +# TODO(b/369686096): drop this when 5.10 is gone. +ifeq ($(wildcard $(TARGET_KERNEL_DIR)/init.insmod.*.cfg),) PRODUCT_COPY_FILES += \ - device/google/felix/init.insmod.felix.cfg:$(TARGET_COPY_OUT_VENDOR)/etc/init.insmod.felix.cfg + device/google/felix/init.insmod.felix.cfg:$(TARGET_COPY_OUT_VENDOR_DLKM)/etc/init.insmod.felix.cfg +endif # Camera PRODUCT_COPY_FILES += \ @@ -108,6 +112,12 @@ PRODUCT_PACKAGES += \ android.hardware.nfc-service.st \ NfcOverlayFelix +# Shared Modem Platform +SHARED_MODEM_PLATFORM_VENDOR := lassen + +# Shared Modem Platform +include device/google/gs-common/modem/modem_svc_sit/shared_modem_platform.mk + # SecureElement PRODUCT_PACKAGES += \ android.hardware.secure_element@1.2-service-gto \ @@ -423,7 +433,7 @@ PRODUCT_COPY_FILES += \ # LE Audio Unicast Allowlist PRODUCT_PRODUCT_PROPERTIES += \ - persist.bluetooth.leaudio.allow_list=SM-R510,WF-1000XM5 + persist.bluetooth.leaudio.allow_list=SM-R510,WF-1000XM5,SM-R630 # Bluetooth EWP test tool PRODUCT_PACKAGES_ENG += \ diff --git a/felix/overlay/frameworks/base/core/res/res/xml/power_profile.xml b/felix/overlay/frameworks/base/core/res/res/xml/power_profile.xml index b633087..1c8a7e5 100644 --- a/felix/overlay/frameworks/base/core/res/res/xml/power_profile.xml +++ b/felix/overlay/frameworks/base/core/res/res/xml/power_profile.xml @@ -151,13 +151,17 @@ - 32 + 32 + 32 - 98 + 98 + 98 + - 470 + 470 + 470 240.47 diff --git a/nfc/libnfc-hal-st.conf b/nfc/libnfc-hal-st.conf index 7300e21..ac8c20d 100644 --- a/nfc/libnfc-hal-st.conf +++ b/nfc/libnfc-hal-st.conf @@ -135,7 +135,7 @@ OFFHOST_ROUTE_ESE={86} # host 0x00 # eSE 0x82 (eSE), 0x86 (eUICC/SPI-SE) # UICC 0x81 (UICC_1), 0x85 (UICC_2) -DEFAULT_ISODEP_ROUTE=0x81 +DEFAULT_ISODEP_ROUTE=0x00 ############################################################################### # Configure the HAL Clock control diff --git a/powerhint.json b/powerhint.json index 1c88dd5..2074a8e 100644 --- a/powerhint.json +++ b/powerhint.json @@ -879,24 +879,30 @@ "Duration": 5000, "Value": "0" }, - { - "PowerHint": "CPU_LOAD_RESET", - "Node": "GPUMinFreq", - "Duration": 50, - "Value": "302000" - }, { "PowerHint": "DISPLAY_INACTIVE", "Node": "MemFreq", "Duration": 0, "Value": "421000" }, + { + "PowerHint": "CPU_LOAD_RESET", + "Node": "GPUMinFreq", + "Duration": 50, + "Value": "302000" + }, { "PowerHint": "CPU_LOAD_RESET", "Node": "MemFreq", "Duration": 33, "Value": "1014000" }, + { + "PowerHint": "CPU_LOAD_RESET", + "Node": "TAPreferHighCap", + "Duration": 33, + "Value": "1" + }, { "PowerHint": "CAMERA_LAUNCH", "Node": "MemFreq", @@ -1107,6 +1113,18 @@ "Duration": 100, "Value": "0" }, + { + "PowerHint": "CAMERA_MULTICAM_BOOST", + "Node": "CDPreferIdle", + "Duration": 100, + "Value": "1" + }, + { + "PowerHint": "CAMERA_MULTICAM_BOOST", + "Node": "PMU_POLL", + "Duration": 100, + "Value": "0" + }, { "PowerHint": "GCA_CAMERA_SHOT_BIGCPU_RANK1", "Node": "TAPreferHighCap", diff --git a/rro_overlays/WifiOverlay/res/values/config.xml b/rro_overlays/WifiOverlay/res/values/config.xml index 8e45a9f..516591f 100644 --- a/rro_overlays/WifiOverlay/res/values/config.xml +++ b/rro_overlays/WifiOverlay/res/values/config.xml @@ -175,4 +175,6 @@ false: firmware roaming will not be affected. --> true + + false diff --git a/vibrator/OWNERS b/vibrator/OWNERS index dec74a8..fc59b13 100644 --- a/vibrator/OWNERS +++ b/vibrator/OWNERS @@ -1 +1,3 @@ -file:platform/hardware/google/pixel:/vibrator/OWNERS +chrispaulo@google.com +nathankulczak@google.com +taikuo@google.com diff --git a/vibrator/common/HardwareBase.cpp b/vibrator/common/HardwareBase.cpp index 329293a..583caaa 100644 --- a/vibrator/common/HardwareBase.cpp +++ b/vibrator/common/HardwareBase.cpp @@ -69,6 +69,7 @@ HwCalBase::HwCalBase() { std::ifstream calfile; std::ifstream calfile_dual; auto propertyPrefix = std::getenv("PROPERTY_PREFIX"); + auto calPath = std::getenv("CALIBRATION_FILEPATH"); if (propertyPrefix != NULL) { mPropertyPrefix = std::string(propertyPrefix); @@ -76,6 +77,14 @@ HwCalBase::HwCalBase() { ALOGE("Failed get property prefix!"); } + // Keep the cal file path for the current HwCalBase instance. + if (calPath != NULL) { + mCalPath = std::string(calPath); + } else { + ALOGE("Failed get the calibration file path!"); + } + + // Read the cal data for the current instance. utils::fileFromEnv("CALIBRATION_FILEPATH", &calfile); for (std::string line; std::getline(calfile, line);) { @@ -89,6 +98,7 @@ HwCalBase::HwCalBase() { } } + // Read the cal data for the other instance. utils::fileFromEnv("CALIBRATION_FILEPATH_DUAL", &calfile_dual); for (std::string line; std::getline(calfile_dual, line);) { @@ -106,7 +116,6 @@ HwCalBase::HwCalBase() { void HwCalBase::debug(int fd) { std::ifstream stream; - std::string path; std::string line; struct context { HwCalBase *obj; @@ -133,9 +142,8 @@ void HwCalBase::debug(int fd) { dprintf(fd, "Persist:\n"); - utils::fileFromEnv("CALIBRATION_FILEPATH", &stream, &path); - - dprintf(fd, " %s:\n", path.c_str()); + utils::openNoCreate(mCalPath, &stream); + dprintf(fd, " %s:\n", mCalPath.c_str()); while (std::getline(stream, line)) { dprintf(fd, " %s\n", line.c_str()); } diff --git a/vibrator/common/HardwareBase.h b/vibrator/common/HardwareBase.h index f09fada..0296390 100644 --- a/vibrator/common/HardwareBase.h +++ b/vibrator/common/HardwareBase.h @@ -208,6 +208,7 @@ class HwCalBase { private: std::string mPropertyPrefix; + std::string mCalPath; std::map mCalData; }; diff --git a/vibrator/common/utils.h b/vibrator/common/utils.h index 86dd37e..b5005a6 100644 --- a/vibrator/common/utils.h +++ b/vibrator/common/utils.h @@ -103,6 +103,19 @@ inline Enable_If_Unsigned getProperty(const std::string &key, const T def) return ::android::base::GetUintProperty(key, def); } +template +inline std::array getProperty(const std::string &key, const std::array &def) { + std::string value = ::android::base::GetProperty(key, ""); + if (!value.empty()) { + std::array result{0}; + std::stringstream stream{value}; + utils::unpack(stream, &result); + if (stream && stream.eof()) + return result; + } + return def; +} + template <> inline bool getProperty(const std::string &key, const bool def) { return ::android::base::GetBoolProperty(key, def); diff --git a/vibrator/cs40l26/Android.bp b/vibrator/cs40l26/Android.bp index bd5047a..e929343 100644 --- a/vibrator/cs40l26/Android.bp +++ b/vibrator/cs40l26/Android.bp @@ -60,7 +60,7 @@ cc_library { srcs: [ "Vibrator.cpp", ], - shared_libs: ["//hardware/google/pixel:PixelVibratorFlagsL26"], + shared_libs: ["//device/google/gs-common:PixelVibratorFlagsL26"], export_include_dirs: ["."], vendor_available: true, visibility: [":__subpackages__"], diff --git a/vibrator/cs40l26/Hardware.h b/vibrator/cs40l26/Hardware.h index e2c2d36..e4dd344 100644 --- a/vibrator/cs40l26/Hardware.h +++ b/vibrator/cs40l26/Hardware.h @@ -318,9 +318,9 @@ class HwCal : public Vibrator::HwCal, private HwCalBase { static constexpr uint32_t VERSION_DEFAULT = 2; static constexpr int32_t DEFAULT_FREQUENCY_SHIFT = 0; - static constexpr std::array V_TICK_DEFAULT = {1, 100}; - static constexpr std::array V_CLICK_DEFAULT = {1, 100}; - static constexpr std::array V_LONG_DEFAULT = {1, 100}; + static constexpr std::array V_TICK_DEFAULT = {5, 95}; + static constexpr std::array V_CLICK_DEFAULT = {5, 95}; + static constexpr std::array V_LONG_DEFAULT = {5, 95}; public: HwCal() {} @@ -370,22 +370,19 @@ class HwCal : public Vibrator::HwCal, private HwCalBase { if (getPersist(TICK_VOLTAGES_CONFIG, value)) { return true; } - *value = V_TICK_DEFAULT; - return true; + return getProperty(TICK_VOLTAGES_CONFIG, value, V_TICK_DEFAULT); } bool getClickVolLevels(std::array *value) override { if (getPersist(CLICK_VOLTAGES_CONFIG, value)) { return true; } - *value = V_CLICK_DEFAULT; - return true; + return getProperty(CLICK_VOLTAGES_CONFIG, value, V_CLICK_DEFAULT); } bool getLongVolLevels(std::array *value) override { if (getPersist(LONG_VOLTAGES_CONFIG, value)) { return true; } - *value = V_LONG_DEFAULT; - return true; + return getProperty(LONG_VOLTAGES_CONFIG, value, V_LONG_DEFAULT); } bool isChirpEnabled() override { return utils::getProperty("persist.vendor.vibrator.hal.chirp.enabled", false); diff --git a/vibrator/cs40l26/Vibrator.cpp b/vibrator/cs40l26/Vibrator.cpp index 0fe4880..36d8e8c 100644 --- a/vibrator/cs40l26/Vibrator.cpp +++ b/vibrator/cs40l26/Vibrator.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -92,6 +93,30 @@ static constexpr uint8_t PWLE_CHIRP_BIT = 0x8; // Dynamic/static frequency and static constexpr uint8_t PWLE_BRAKE_BIT = 0x4; static constexpr uint8_t PWLE_AMP_REG_BIT = 0x2; +static constexpr uint8_t PWLE_WT_TYPE = 12; +static constexpr uint8_t PWLE_HEADER_WORD_COUNT = 3; +static constexpr uint8_t PWLE_HEADER_FTR_SHIFT = 8; +static constexpr uint8_t PWLE_SVC_METADATA_WORD_COUNT = 3; +static constexpr uint32_t PWLE_SVC_METADATA_TERMINATOR = 0xFFFFFF; +static constexpr uint8_t PWLE_SEGMENT_WORD_COUNT = 2; +static constexpr uint8_t PWLE_HEADER_WCOUNT_WORD_OFFSET = 2; +static constexpr uint8_t PWLE_WORD_SIZE = sizeof(uint32_t); + +static constexpr uint8_t PWLE_SVC_NO_BRAKING = -1; +static constexpr uint8_t PWLE_SVC_CAT_BRAKING = 0; +static constexpr uint8_t PWLE_SVC_OPEN_BRAKING = 1; +static constexpr uint8_t PWLE_SVC_CLOSED_BRAKING = 2; +static constexpr uint8_t PWLE_SVC_MIXED_BRAKING = 3; + +static constexpr uint32_t PWLE_SVC_MAX_BRAKING_TIME_MS = 1000; + +static constexpr uint8_t PWLE_FTR_BUZZ_BIT = 0x80; +static constexpr uint8_t PWLE_FTR_CLICK_BIT = 0x00; +static constexpr uint8_t PWLE_FTR_DYNAMIC_F0_BIT = 0x10; +static constexpr uint8_t PWLE_FTR_SVC_METADATA_BIT = 0x04; +static constexpr uint8_t PWLE_FTR_DVL_BIT = 0x02; +static constexpr uint8_t PWLE_FTR_LF0T_BIT = 0x01; + static constexpr float PWLE_LEVEL_MIN = 0.0; static constexpr float PWLE_LEVEL_MAX = 1.0; static constexpr float CS40L26_PWLE_LEVEL_MIN = -1.0; @@ -170,6 +195,8 @@ enum vibe_state { VIBE_STATE_ASP, }; +std::mutex mActiveId_mutex; // protects mActiveId + class DspMemChunk { private: std::unique_ptr head; @@ -245,10 +272,18 @@ class DspMemChunk { write(8, 0); /* nsections placeholder */ write(8, 0); /* repeat */ } else if (waveformType == WAVEFORM_PWLE) { + write(16, (PWLE_FTR_BUZZ_BIT | PWLE_FTR_DVL_BIT) + << PWLE_HEADER_FTR_SHIFT); /* Feature flag */ + write(8, PWLE_WT_TYPE); /* type12 */ + write(24, PWLE_HEADER_WORD_COUNT); /* Header word count */ + write(24, 0); /* Body word count placeholder */ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) write(24, 0); /* Waveform length placeholder */ write(8, 0); /* Repeat */ write(12, 0); /* Wait time between repeats */ write(8, 0); /* nsections placeholder */ +#endif } else { ALOGE("%s: Invalid type: %u", __func__, waveformType); } @@ -336,6 +371,9 @@ class DspMemChunk { ALOGE("%s: Invalid argument: %u", __func__, totalDuration); return -EINVAL; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) + f += PWLE_HEADER_WORD_COUNT * PWLE_WORD_SIZE; +#endif totalDuration *= 8; /* Unit: 0.125 ms (since wlength played @ 8kHz). */ totalDuration |= WT_LEN_CALCD; /* Bit 23 is for WT_LEN_CALCD; Bit 22 is for WT_INDEFINITE. */ @@ -364,6 +402,9 @@ class DspMemChunk { ALOGE("%s: Invalid argument: %d", __func__, segmentIdx); return -EINVAL; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) + f += PWLE_HEADER_WORD_COUNT * PWLE_WORD_SIZE; +#endif *(f + 7) |= (0xF0 & segmentIdx) >> 4; /* Bit 4 to 7 */ *(f + 9) |= (0x0F & segmentIdx) << 4; /* Bit 3 to 0 */ } else { @@ -373,6 +414,34 @@ class DspMemChunk { return 0; } + + int updateWCount(int segmentCount) { + uint8_t *f = front(); + + if (segmentCount > COMPOSE_SIZE_MAX + 1 /*1st effect may have a delay*/) { + ALOGE("%s: Invalid argument: %d", __func__, segmentCount); + return -EINVAL; + } + if (f == nullptr) { + ALOGE("%s: head does not exist!", __func__); + return -ENOMEM; + } + if (waveformType != WAVEFORM_PWLE) { + ALOGE("%s: Invalid type: %d", __func__, waveformType); + return -EDOM; + } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) + f += PWLE_HEADER_WORD_COUNT * PWLE_WORD_SIZE; +#endif + uint32_t dataSize = segmentCount * PWLE_SEGMENT_WORD_COUNT + PWLE_HEADER_WORD_COUNT; + *(f + 0) = (dataSize >> 24) & 0xFF; + *(f + 1) = (dataSize >> 16) & 0xFF; + *(f + 2) = (dataSize >> 8) & 0xFF; + *(f + 3) = dataSize & 0xFF; + + return 0; + } }; Vibrator::Vibrator(std::unique_ptr hwApiDefault, std::unique_ptr hwCalDefault, @@ -1014,7 +1083,7 @@ ndk::ScopedAStatus Vibrator::on(uint32_t timeoutMs, uint32_t effectIndex, const if (mIsDual) { mHwApiDual->getOwtFreeSpace(&freeBytes); if (ch-> size() > freeBytes) { - ALOGE("Invalid OWT length in flip: Effect %d: %d > %d!", effectIndex, + ALOGE("Invalid OWT length in flip: Effect %d: %zu > %d!", effectIndex, ch-> size(), freeBytes); return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } @@ -1370,6 +1439,13 @@ ndk::ScopedAStatus Vibrator::composePwle(const std::vector &compo return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } + /* Update word count */ + if (ch.updateWCount(segmentIdx) < 0) { + ALOGE("%s: Failed to update the waveform word count", __func__); + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + + /* Update waveform length */ if (ch.updateWLength(totalDuration) < 0) { ALOGE("%s: Failed to update the waveform length length", __func__); return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); @@ -1408,40 +1484,31 @@ binder_status_t Vibrator::dump(int fd, const char **args, uint32_t numArgs) { dprintf(fd, " Redc: %.02f\n", mRedc); dprintf(fd, " Voltage Levels:\n"); - dprintf(fd, " Tick Effect Min: %" PRIu32 " Max: %" PRIu32 "\n", mTickEffectVol[0], + dprintf(fd, " Tick Effect Min: %" PRIu32 " Max: %" PRIu32 "\n", mTickEffectVol[0], mTickEffectVol[1]); - dprintf(fd, " Click Effect Min: %" PRIu32 " Max: %" PRIu32 "\n", mClickEffectVol[0], + dprintf(fd, " Click Effect Min: %" PRIu32 " Max: %" PRIu32 "\n", mClickEffectVol[0], mClickEffectVol[1]); - dprintf(fd, " Long Effect Min: %" PRIu32 " Max: %" PRIu32 "\n", mLongEffectVol[0], + dprintf(fd, " Long Effect Min: %" PRIu32 " Max: %" PRIu32 "\n", mLongEffectVol[0], mLongEffectVol[1]); - dprintf(fd, " FF effect:\n"); - dprintf(fd, " Physical waveform:\n"); - dprintf(fd, "==== Base ====\n\tId\tIndex\tt ->\tt'\tBrake\ttrigger button\n"); uint8_t effectId; + dprintf(fd, " Scales\n"); + dprintf(fd, "\tId\tMinScale\tMaxScale\n"); + for (effectId = 0; effectId < WAVEFORM_MAX_PHYSICAL_INDEX; effectId++) { + dprintf(fd, "\t%d\t%d\t\t%d\n", effectId, mPrimitiveMinScale[effectId], + mPrimitiveMaxScale[effectId]); + } + + dprintf(fd, " Base FF effect:\n"); + dprintf(fd, " Physical waveform:\n"); + dprintf(fd, "\tId\tIndex\tt ->\tt'\tBrake\ttrigger button\n"); for (effectId = 0; effectId < WAVEFORM_MAX_PHYSICAL_INDEX; effectId++) { dprintf(fd, "\t%d\t%d\t%d\t%d\t%d\t%X\n", mFfEffects[effectId].id, mFfEffects[effectId].u.periodic.custom_data[1], mEffectDurations[effectId], mFfEffects[effectId].replay.length, mEffectBrakingDurations[effectId], mFfEffects[effectId].trigger.button); } - if (mIsDual) { - dprintf(fd, "==== Flip ====\n\tId\tIndex\tt ->\tt'\tBrake\ttrigger button\n"); - for (effectId = 0; effectId < WAVEFORM_MAX_PHYSICAL_INDEX; effectId++) { - dprintf(fd, "\t%d\t%d\t%d\t%d\t%d\t%X\n", mFfEffectsDual[effectId].id, - mFfEffectsDual[effectId].u.periodic.custom_data[1], mEffectDurations[effectId], - mFfEffectsDual[effectId].replay.length, mEffectBrakingDurations[effectId], - mFfEffectsDual[effectId].trigger.button); - } - } - - dprintf(fd, "==== Scales ====\n\tId\tMinScale\tMaxScale\n"); - for (effectId = 0; effectId < WAVEFORM_MAX_PHYSICAL_INDEX; effectId++) { - dprintf(fd, "\t%d\t%d\t\t%d\n", effectId, mPrimitiveMinScale[effectId], - mPrimitiveMaxScale[effectId]); - } - - dprintf(fd, "\nBase: OWT waveform:\n"); + dprintf(fd, " OWT waveform:\n"); dprintf(fd, "\tId\tBytes\tData\tt\ttrigger button\n"); for (effectId = WAVEFORM_MAX_PHYSICAL_INDEX; effectId < WAVEFORM_MAX_INDEX; effectId++) { uint32_t numBytes = mFfEffects[effectId].u.periodic.custom_len * 2; @@ -1457,8 +1524,18 @@ binder_status_t Vibrator::dump(int fd, const char **args, uint32_t numArgs) { dprintf(fd, "\t%d\t%d\t{%s}\t%u\t%X\n", mFfEffects[effectId].id, numBytes, ss.str().c_str(), mFfEffectsDual[effectId].replay.length, mFfEffects[effectId].trigger.button); } + if (mIsDual) { - dprintf(fd, "Flip: OWT waveform:\n"); + dprintf(fd, " Flip FF effect:\n"); + dprintf(fd, " Physical waveform:\n"); + dprintf(fd, "\tId\tIndex\tt ->\tt'\tBrake\ttrigger button\n"); + for (effectId = 0; effectId < WAVEFORM_MAX_PHYSICAL_INDEX; effectId++) { + dprintf(fd, "\t%d\t%d\t%d\t%d\t%d\t%X\n", mFfEffectsDual[effectId].id, + mFfEffectsDual[effectId].u.periodic.custom_data[1], mEffectDurations[effectId], + mFfEffectsDual[effectId].replay.length, mEffectBrakingDurations[effectId], + mFfEffectsDual[effectId].trigger.button); + } + dprintf(fd, " OWT waveform:\n"); dprintf(fd, "\tId\tBytes\tData\tt\ttrigger button\n"); for (effectId = WAVEFORM_MAX_PHYSICAL_INDEX; effectId < WAVEFORM_MAX_INDEX; effectId++) { uint32_t numBytes = mFfEffectsDual[effectId].u.periodic.custom_len * 2; @@ -1479,78 +1556,67 @@ binder_status_t Vibrator::dump(int fd, const char **args, uint32_t numArgs) { dprintf(fd, "\n"); dprintf(fd, "Versions:\n"); + const std::vector> moduleFolderNames = { + {"cs40l26_core", "Haptics"}, {"cl_dsp_core", "DSP"}}; + const std::string firmwareFolder = "/vendor/firmware/"; + const std::string waveformName = "cs40l26.bin"; + const std::array firmwareFileNames = {"cs40l26.wmfw", "cs40l26-calib.wmfw"}; + const std::array tuningFileNames = {"cs40l26-svc.bin", "cs40l26-calib.bin", + "cs40l26-dvl.bin", "cs40l26-dbc.bin"}; std::ifstream verFile; const auto verBinFileMode = std::ifstream::in | std::ifstream::binary; std::string ver; - verFile.open("/sys/module/cs40l26_core/version"); - if (verFile.is_open()) { - getline(verFile, ver); - dprintf(fd, " Haptics Driver: %s\n", ver.c_str()); - verFile.close(); + for (const auto &[folder, logTag] : moduleFolderNames) { + verFile.open("/sys/module/" + folder + "/version"); + if (verFile.is_open()) { + getline(verFile, ver); + dprintf(fd, " %s Driver: %s\n", logTag.c_str(), ver.c_str()); + verFile.close(); + } } - verFile.open("/sys/module/cl_dsp_core/version"); - if (verFile.is_open()) { - getline(verFile, ver); - dprintf(fd, " DSP Driver: %s\n", ver.c_str()); - verFile.close(); + for (auto &name : firmwareFileNames) { + verFile.open(firmwareFolder + name, verBinFileMode); + if (verFile.is_open()) { + verFile.seekg(113); + dprintf(fd, " %s: %d.%d.%d\n", name.c_str(), verFile.get(), verFile.get(), + verFile.get()); + verFile.close(); + } } - verFile.open("/vendor/firmware/cs40l26.wmfw", verBinFileMode); - if (verFile.is_open()) { - verFile.seekg(113); - dprintf(fd, " cs40l26.wmfw: %d.%d.%d\n", verFile.get(), verFile.get(), verFile.get()); - verFile.close(); - } - verFile.open("/vendor/firmware/cs40l26-calib.wmfw", verBinFileMode); - if (verFile.is_open()) { - verFile.seekg(113); - dprintf(fd, " cs40l26-calib.wmfw: %d.%d.%d\n", verFile.get(), verFile.get(), - verFile.get()); - verFile.close(); - } - verFile.open("/vendor/firmware/cs40l26.bin", verBinFileMode); + verFile.open(firmwareFolder + waveformName, verBinFileMode); if (verFile.is_open()) { while (getline(verFile, ver)) { auto pos = ver.find("Date: "); if (pos != std::string::npos) { ver = ver.substr(pos + 6, pos + 15); - dprintf(fd, " cs40l26.bin: %s\n", ver.c_str()); + dprintf(fd, " %s: %s\n", waveformName.c_str(), ver.c_str()); break; } } verFile.close(); } - verFile.open("/vendor/firmware/cs40l26-svc.bin", verBinFileMode); - if (verFile.is_open()) { - verFile.seekg(36); - getline(verFile, ver); - ver = ver.substr(ver.rfind('\\') + 1); - dprintf(fd, " cs40l26-svc.bin: %s\n", ver.c_str()); - verFile.close(); - } - verFile.open("/vendor/firmware/cs40l26-calib.bin", verBinFileMode); - if (verFile.is_open()) { - verFile.seekg(36); - getline(verFile, ver); - ver = ver.substr(ver.rfind('\\') + 1); - dprintf(fd, " cs40l26-calib.bin: %s\n", ver.c_str()); - verFile.close(); - } - verFile.open("/vendor/firmware/cs40l26-dvl.bin", verBinFileMode); - if (verFile.is_open()) { - verFile.seekg(36); - getline(verFile, ver); - ver = ver.substr(0, ver.find('\0') + 1); - ver = ver.substr(ver.rfind('\\') + 1); - dprintf(fd, " cs40l26-dvl.bin: %s\n", ver.c_str()); - verFile.close(); + for (auto &name : tuningFileNames) { + verFile.open(firmwareFolder + name, verBinFileMode); + if (verFile.is_open()) { + verFile.seekg(36); + getline(verFile, ver); + ver = ver.substr(0, ver.find(".bin") + 4); + ver = ver.substr(ver.rfind('\\') + 1); + dprintf(fd, " %s: %s\n", name.c_str(), ver.c_str()); + verFile.close(); + } } + dprintf(fd, "\n"); + mHwApiDef->debug(fd); dprintf(fd, "\n"); mHwCalDef->debug(fd); + dprintf(fd, "\n"); + if (mIsDual) { mHwApiDual->debug(fd); dprintf(fd, "\n"); @@ -1856,7 +1922,6 @@ uint32_t Vibrator::intensityToVolLevel(float intensity, uint32_t effectIndex) { volLevel = calc(intensity, mClickEffectVol); break; } - // The waveform being played must fall within the allowable scale range if (effectIndex < WAVEFORM_MAX_INDEX) { if (volLevel > mPrimitiveMaxScale[effectIndex]) { diff --git a/vibrator/cs40l26/Vibrator.h b/vibrator/cs40l26/Vibrator.h index a61cea9..6fc3a3d 100644 --- a/vibrator/cs40l26/Vibrator.h +++ b/vibrator/cs40l26/Vibrator.h @@ -250,7 +250,6 @@ class Vibrator : public BnVibrator { bool mConfigHapticAlsaDeviceDone{false}; bool mGPIOStatus; bool mIsDual{false}; - std::mutex mActiveId_mutex; // protects mActiveId }; } // namespace vibrator diff --git a/vibrator/cs40l26/tests/test-hwcal.cpp b/vibrator/cs40l26/tests/test-hwcal.cpp index e482b6c..5223c85 100644 --- a/vibrator/cs40l26/tests/test-hwcal.cpp +++ b/vibrator/cs40l26/tests/test-hwcal.cpp @@ -30,9 +30,9 @@ using ::testing::Test; class HwCalTest : public Test { protected: - static constexpr std::array V_TICK_DEFAULT = {1, 100}; - static constexpr std::array V_CLICK_DEFAULT = {1, 100}; - static constexpr std::array V_LONG_DEFAULT = {1, 100}; + static constexpr std::array V_TICK_DEFAULT = {5, 95}; + static constexpr std::array V_CLICK_DEFAULT = {5, 95}; + static constexpr std::array V_LONG_DEFAULT = {5, 95}; public: void SetUp() override { setenv("CALIBRATION_FILEPATH", mCalFile.path, true); } diff --git a/vibrator/cs40l26/tests/test-vibrator.cpp b/vibrator/cs40l26/tests/test-vibrator.cpp index 6c8cebb..b9b5b3c 100644 --- a/vibrator/cs40l26/tests/test-vibrator.cpp +++ b/vibrator/cs40l26/tests/test-vibrator.cpp @@ -87,7 +87,7 @@ static const std::map EFFECT_INDEX{ static constexpr uint32_t MIN_ON_OFF_INTERVAL_US = 8500; static constexpr uint8_t VOLTAGE_SCALE_MAX = 100; static constexpr int8_t MAX_COLD_START_LATENCY_MS = 6; // I2C Transaction + DSP Return-From-Standby -static constexpr auto POLLING_TIMEOUT = 20; +static constexpr auto POLLING_TIMEOUT = 50; enum WaveformIndex : uint16_t { /* Physical waveform */ WAVEFORM_LONG_VIBRATION_EFFECT_INDEX = 0, @@ -506,6 +506,23 @@ TEST_P(EffectsTest, perform) { promise.set_value(); return ndk::ScopedAStatus::ok(); }; + std::vector primitiveMaxScale; + std::vector primitiveMinScale; + primitiveMaxScale.resize(WAVEFORM_MAX_INDEX, 100); + primitiveMaxScale[WAVEFORM_CLICK_INDEX] = 95; + primitiveMaxScale[WAVEFORM_THUD_INDEX] = 75; + primitiveMaxScale[WAVEFORM_SPIN_INDEX] = 90; + primitiveMaxScale[WAVEFORM_LIGHT_TICK_INDEX] = 75; + primitiveMaxScale[WAVEFORM_LOW_TICK_INDEX] = 75; + + primitiveMinScale.resize(WAVEFORM_MAX_INDEX, 0); + primitiveMinScale[WAVEFORM_CLICK_INDEX] = 1; + primitiveMinScale[WAVEFORM_THUD_INDEX] = 11; + primitiveMinScale[WAVEFORM_SPIN_INDEX] = 23; + primitiveMinScale[WAVEFORM_SLOW_RISE_INDEX] = 25; + primitiveMinScale[WAVEFORM_QUICK_FALL_INDEX] = 2; + primitiveMinScale[WAVEFORM_LIGHT_TICK_INDEX] = 3; + primitiveMinScale[WAVEFORM_LOW_TICK_INDEX] = 16; bool composeEffect; ExpectationSet eSetup; @@ -515,7 +532,18 @@ TEST_P(EffectsTest, perform) { EffectIndex index = EFFECT_INDEX.at(effect); duration = EFFECT_DURATIONS[index]; - eSetup += EXPECT_CALL(*mMockApi, setFFGain(_, levelToScale(scale->second))) + auto updatedScale = levelToScale(scale->second); + + if (index < WAVEFORM_MAX_INDEX) { + if (updatedScale > primitiveMaxScale[index]) { + updatedScale = primitiveMaxScale[index]; + } + if (updatedScale < primitiveMinScale[index]) { + updatedScale = primitiveMinScale[index]; + } + } + + eSetup += EXPECT_CALL(*mMockApi, setFFGain(_, updatedScale)) .WillOnce(DoDefault()); eActivate = EXPECT_CALL(*mMockApi, setFFPlay(_, index, true)) .After(eSetup)