diff options
author | Fenglin Wu <fenglinw@codeaurora.org> | 2020-03-12 09:13:18 +0800 |
---|---|---|
committer | Fenglin Wu <fenglinw@codeaurora.org> | 2020-04-15 14:46:38 +0800 |
commit | adda2bc784be8d94c5267ce0efa91a5e874549ab (patch) | |
tree | edb6505f6d266810c7808c512631755baf409510 | |
parent | 8051b1d026816d9c762ab37e90d91fec12a5d683 (diff) |
vibrator: restructure to support V1.3 interface
Vibrator interface V1.3 adds support for external control to support
audio haptics. With the current design, it is difficult to support both
V1.2 and V1.3 for different targets together. Hence, restructure the
vibrator HAL code to add support for V1.3 vibrator interface. Also,
make a change to keep the service running even if vibrator device is
not detected to satisfy the requirement of QMAA. However, still keep
the QMAA implementation in case if there is any further usage.
Change-Id: I3eb07619f6553dfde4ad9f5f89a780a5bcee0f95
-rw-r--r-- | 1.2/Android.bp | 45 | ||||
-rw-r--r-- | 1.2/Vibrator.cpp (renamed from Vibrator.cpp) | 226 | ||||
-rw-r--r-- | 1.2/Vibrator_1_2.h | 82 | ||||
-rw-r--r-- | 1.2/service.cpp (renamed from service.cpp) | 70 | ||||
-rw-r--r-- | 1.2/vendor.qti.hardware.vibrator@1.2-service.rc (renamed from vendor.qti.hardware.vibrator@1.2-service.rc) | 0 | ||||
-rw-r--r-- | 1.2/vendor.qti.hardware.vibrator@1.2-service.xml | 38 | ||||
-rw-r--r-- | 1.3/Android.bp | 26 | ||||
-rw-r--r-- | 1.3/Vibrator.cpp | 153 | ||||
-rw-r--r-- | 1.3/Vibrator_1_3.h | 70 | ||||
-rw-r--r-- | 1.3/service.cpp | 55 | ||||
-rw-r--r-- | 1.3/vendor.qti.hardware.vibrator@1.3-service.rc | 4 | ||||
-rw-r--r-- | 1.3/vendor.qti.hardware.vibrator@1.3-service.xml | 38 | ||||
-rw-r--r-- | qmaa/Android.bp (renamed from Android.bp) | 13 | ||||
-rw-r--r-- | qmaa/Vibrator_qmaa.h (renamed from Vibrator.h) | 0 | ||||
-rw-r--r-- | qmaa/service_qmaa.cpp (renamed from service_qmaa.cpp) | 4 | ||||
-rw-r--r-- | qmaa/vendor.qti.hardware.vibrator@1.2-service.rc | 4 | ||||
-rw-r--r-- | vibrator-vendor-product.mk | 22 |
17 files changed, 669 insertions, 181 deletions
diff --git a/1.2/Android.bp b/1.2/Android.bp new file mode 100644 index 0000000..61d1667 --- /dev/null +++ b/1.2/Android.bp @@ -0,0 +1,45 @@ +Common_CFlags = ["-Wall"] +Common_CFlags += ["-Werror"] + +cc_library_shared { + name: "vendor.qti.hardware.vibrator@1.2-impl", + vendor: true, + cflags: Common_CFlags, + srcs: [ + "Vibrator.cpp", + ], + shared_libs: [ + "libcutils", + "liblog", + "libutils", + "libhardware", + "libhidlbase", + "android.hardware.vibrator@1.0", + "android.hardware.vibrator@1.1", + "android.hardware.vibrator@1.2", + ], + export_include_dirs: ["."] +} + +cc_binary { + name: "vendor.qti.hardware.vibrator@1.2-service", + vendor: true, + relative_install_path: "hw", + init_rc: ["vendor.qti.hardware.vibrator@1.2-service.rc"], + cflags: Common_CFlags, + srcs: [ + "service.cpp", + ], + shared_libs: [ + "libcutils", + "liblog", + "libutils", + "libhardware", + "libhidlbase", + "android.hardware.vibrator@1.2", + "vendor.qti.hardware.vibrator@1.2-impl", + ], + vintf_fragments: [ + "vendor.qti.hardware.vibrator@1.2-service.xml", + ], +} diff --git a/Vibrator.cpp b/1.2/Vibrator.cpp index 9d68660..1732a55 100644 --- a/Vibrator.cpp +++ b/1.2/Vibrator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -27,16 +27,18 @@ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#define LOG_TAG "VibratorService.qti" +#define LOG_TAG "vendor.qti.vibrator@1.2-impl" #include <hardware/hardware.h> #include <hardware/vibrator.h> +#include <dirent.h> #include <inttypes.h> #include <linux/input.h> #include <log/log.h> +#include <string.h> #include <sys/ioctl.h> -#include "Vibrator.h" +#include "Vibrator_1_2.h" namespace android { namespace hardware { @@ -44,55 +46,119 @@ namespace vibrator { namespace V1_2 { namespace implementation { +using Status = ::android::hardware::vibrator::V1_0::Status; +using EffectStrength = ::android::hardware::vibrator::V1_0::EffectStrength; + #define STRONG_MAGNITUDE 0x7fff #define MEDIUM_MAGNITUDE 0x5fff #define LIGHT_MAGNITUDE 0x3fff +#define INVALID_VALUE -1 + +#define test_bit(bit, array) ((array)[(bit)/8] & (1<<((bit)%8))) + +InputFFDevice::InputFFDevice() +{ + DIR *dp; + struct dirent *dir; + uint8_t ffBitmask[FF_CNT / 8]; + char devicename[PATH_MAX]; + const char *INPUT_DIR = "/dev/input/"; + int fd, ret; + + mVibraFd = INVALID_VALUE; + mSupportGain = false; + mSupportEffects = false; + mCurrAppId = INVALID_VALUE; + mCurrMagnitude = 0x7fff; -using Status = ::android::hardware::vibrator::V1_0::Status; + dp = opendir(INPUT_DIR); + if (!dp) { + ALOGE("open %s failed, errno = %d", INPUT_DIR, errno); + return; + } -Vibrator::Vibrator(int vibraFd, bool supportGain, bool supportEffects) : - mVibraFd(vibraFd), mSupportGain(supportGain), - mSupportEffects(supportEffects) { - mCurrAppId = -1; - mCurrEffectId = -1; - mCurrMagnitude = 0x7fff; - mPlayLengthMs = 0; + memset(ffBitmask, 0, sizeof(ffBitmask)); + while ((dir = readdir(dp)) != NULL){ + if (dir->d_name[0] == '.' && + (dir->d_name[1] == '\0' || + (dir->d_name[1] == '.' && dir->d_name[2] == '\0'))) + continue; + + snprintf(devicename, PATH_MAX, "%s%s", INPUT_DIR, dir->d_name); + fd = TEMP_FAILURE_RETRY(open(devicename, O_RDWR)); + if (fd < 0) { + ALOGE("open %s failed, errno = %d", devicename, errno); + continue; + } + + ret = TEMP_FAILURE_RETRY(ioctl(fd, EVIOCGBIT(EV_FF, sizeof(ffBitmask)), ffBitmask)); + if (ret == -1) { + ALOGE("ioctl failed, errno = %d", errno); + close(fd); + continue; + } + + if (test_bit(FF_CONSTANT, ffBitmask) || + test_bit(FF_PERIODIC, ffBitmask)) { + mVibraFd = fd; + if (test_bit(FF_CUSTOM, ffBitmask)) + mSupportEffects = true; + if (test_bit(FF_GAIN, ffBitmask)) + mSupportGain = true; + break; + } + + close(fd); + } + + closedir(dp); } /** Play vibration * - * @param timeoutMs: playing length, non-zero means playing; zero means stop playing. - * - * If the request is playing with a predefined effect, the timeoutMs value is - * ignored, and the real playing length is required to be returned from the kernel - * driver for userspace service to wait until the vibration done. - * - * The custom_data in periodic is reused for this usage. It's been defined with - * following format: <effect-ID, play-time-in-seconds, play-time-in-milliseconds>. - * The effect-ID is used for passing down the predefined effect to kernel driver, - * and play-time-xxx is used for return back the real playing length from kernel - * driver. + * @param effectId: ID of the predefined effect will be played. If effectId is valid + * (non-negative value), the timeoutMs value will be ignored, and the + * real playing length will be set in param@playLengtMs and returned + * to VibratorService. If effectId is invalid, value in param@timeoutMs + * will be used as the play length for playing a constant effect. + * @param timeoutMs: playing length, non-zero means playing, zero means stop playing. + * @param playLengthMs: the playing length in ms unit which will be returned to + * VibratorService if the request is playing a predefined effect. + * The custom_data in periodic is reused for returning the playLengthMs + * from kernel space to userspace if the pattern is defined in kernel + * driver. It's been defined with following format: + * <effect-ID, play-time-in-seconds, play-time-in-milliseconds>. + * The effect-ID is used for passing down the predefined effect to + * kernel driver, and the rest two parameters are used for returning + * back the real playing length from kernel driver. */ -Return<Status> Vibrator::play(uint32_t timeoutMs) { +Return<Status> InputFFDevice::play(int effectId, uint32_t timeoutMs, long *playLengthMs) { struct ff_effect effect; struct input_event play; #define CUSTOM_DATA_LEN 3 int16_t data[CUSTOM_DATA_LEN] = {0, 0, 0}; int ret; + /* For QMAA compliance, return OK even if vibrator device doesn't exist */ + if (mVibraFd == INVALID_VALUE) { + if (playLengthMs != NULL) + *playLengthMs = 0; + return Status::OK; + } + if (timeoutMs != 0) { - if (mCurrAppId != -1) { + if (mCurrAppId != INVALID_VALUE) { ret = TEMP_FAILURE_RETRY(ioctl(mVibraFd, EVIOCRMFF, mCurrAppId)); if (ret == -1) { ALOGE("ioctl EVIOCRMFF failed, errno = %d", -errno); goto errout; } - mCurrAppId = -1; + mCurrAppId = INVALID_VALUE; } memset(&effect, 0, sizeof(effect)); - if (mCurrEffectId != -1) { - data[0] = mCurrEffectId; + if (effectId != INVALID_VALUE) { + data[0] = effectId; effect.type = FF_PERIODIC; effect.u.periodic.waveform = FF_CUSTOM; effect.u.periodic.magnitude = mCurrMagnitude; @@ -114,10 +180,8 @@ Return<Status> Vibrator::play(uint32_t timeoutMs) { } mCurrAppId = effect.id; - if (mCurrEffectId != -1) { - mPlayLengthMs = data[1] * 1000 + data[2]; - mCurrEffectId = -1; - } + if (effectId != INVALID_VALUE && playLengthMs != NULL) + *playLengthMs = data[1] * 1000 + data[2]; play.value = 1; play.type = EV_FF; @@ -132,37 +196,34 @@ Return<Status> Vibrator::play(uint32_t timeoutMs) { ALOGE("ioctl EVIOCRMFF failed, errno = %d", -errno); goto errout; } - } else if (mCurrAppId != -1) { + } else if (mCurrAppId != INVALID_VALUE) { ret = TEMP_FAILURE_RETRY(ioctl(mVibraFd, EVIOCRMFF, mCurrAppId)); if (ret == -1) { ALOGE("ioctl EVIOCRMFF failed, errno = %d", -errno); goto errout; } - mCurrAppId = -1; - mPlayLengthMs = 0; + mCurrAppId = INVALID_VALUE; } return Status::OK; errout: - mCurrAppId = -1; - mCurrEffectId = -1; - mPlayLengthMs = 0; + mCurrAppId = INVALID_VALUE; return Status::UNSUPPORTED_OPERATION; } -Return<Status> Vibrator::on(uint32_t timeoutMs) { - return play(timeoutMs); +Return<Status> InputFFDevice::on(uint32_t timeoutMs) { + return play(INVALID_VALUE, timeoutMs, NULL); } -Return<Status> Vibrator::off() { - return play(0); +Return<Status> InputFFDevice::off() { + return play(INVALID_VALUE, 0, NULL); } -Return<bool> Vibrator::supportsAmplitudeControl() { +Return<bool> InputFFDevice::supportsAmplitudeControl() { return mSupportGain ? true : false; } -Return<Status> Vibrator::setAmplitude(uint8_t amplitude) { +Return<Status> InputFFDevice::setAmplitude(uint8_t amplitude) { int tmp, ret; struct input_event ie; @@ -172,6 +233,10 @@ Return<Status> Vibrator::setAmplitude(uint8_t amplitude) { if (amplitude == 0) return Status::BAD_VALUE; + /* For QMAA compliance, return OK even if vibrator device doesn't exist */ + if (mVibraFd == INVALID_VALUE) + return Status::OK; + tmp = amplitude * (STRONG_MAGNITUDE - LIGHT_MAGNITUDE) / 255; tmp += LIGHT_MAGNITUDE; ie.type = EV_FF; @@ -188,48 +253,42 @@ Return<Status> Vibrator::setAmplitude(uint8_t amplitude) { return Status::OK; } -using EffectStrength = ::android::hardware::vibrator::V1_0::EffectStrength; -static int16_t convertEffectStrength(EffectStrength es) { - int16_t magnitude; +Return<Status> InputFFDevice::playEffect(int effectId, EffectStrength es, long *playLengthMs) { + if (!mSupportEffects) + return Status::UNSUPPORTED_OPERATION; switch (es) { case EffectStrength::LIGHT: - magnitude = LIGHT_MAGNITUDE; + mCurrMagnitude = LIGHT_MAGNITUDE; break; case EffectStrength::MEDIUM: - magnitude = MEDIUM_MAGNITUDE; + mCurrMagnitude = MEDIUM_MAGNITUDE; break; case EffectStrength::STRONG: - magnitude = STRONG_MAGNITUDE; + mCurrMagnitude = STRONG_MAGNITUDE; break; default: - return 0; + break; } - return magnitude; + return play(effectId, INVALID_VALUE, playLengthMs); } using Effect_1_0 = ::android::hardware::vibrator::V1_0::Effect; Return<void> Vibrator::perform(Effect_1_0 effect, EffectStrength es, perform_cb _hidl_cb) { Status status; + int effectId = static_cast<int16_t>(effect); + long playLengthMs; - if (!mSupportEffects) { - _hidl_cb(Status::UNSUPPORTED_OPERATION, 0); - return Void(); - } - - mCurrEffectId = static_cast<int16_t>(effect); - mCurrMagnitude = convertEffectStrength(es); - if (mCurrEffectId < (static_cast<int16_t>(Effect_1_0::CLICK)) || - mCurrEffectId > (static_cast<int16_t>(Effect_1_0::DOUBLE_CLICK)) || - mCurrMagnitude == 0) { + if (effectId < (static_cast<int16_t>(Effect_1_0::CLICK)) || + effectId > (static_cast<int16_t>(Effect_1_0::DOUBLE_CLICK))) { _hidl_cb(Status::UNSUPPORTED_OPERATION, 0); return Void(); } - status = play(-1); + status = ff.playEffect(effectId, es, &playLengthMs); if (status == Status::OK) - _hidl_cb(Status::OK, mPlayLengthMs); + _hidl_cb(Status::OK, playLengthMs); else _hidl_cb(Status::UNSUPPORTED_OPERATION, 0); @@ -237,26 +296,20 @@ Return<void> Vibrator::perform(Effect_1_0 effect, EffectStrength es, perform_cb } using Effect_1_1 = ::android::hardware::vibrator::V1_1::Effect_1_1; -Return<void> Vibrator::perform_1_1(Effect_1_1 effect, EffectStrength es, perform_1_1_cb _hidl_cb) { +Return<void> Vibrator::perform_1_1(Effect_1_1 effect, EffectStrength es, perform_cb _hidl_cb) { Status status; + int effectId = static_cast<int16_t>(effect); + long playLengthMs; - if (!mSupportEffects) { - _hidl_cb(Status::UNSUPPORTED_OPERATION, 0); - return Void(); - } - - mCurrEffectId = static_cast<int16_t>(effect); - mCurrMagnitude = convertEffectStrength(es); - if (mCurrEffectId < (static_cast<int16_t>(Effect_1_1::CLICK)) || - mCurrEffectId > (static_cast<int16_t>(Effect_1_1::TICK)) || - mCurrMagnitude == 0) { + if (effectId < (static_cast<int16_t>(Effect_1_1::CLICK)) || + effectId > (static_cast<int16_t>(Effect_1_1::TICK))) { _hidl_cb(Status::UNSUPPORTED_OPERATION, 0); return Void(); } - status = play(-1); + status = ff.playEffect(effectId, es, &playLengthMs); if (status == Status::OK) - _hidl_cb(Status::OK, mPlayLengthMs); + _hidl_cb(Status::OK, playLengthMs); else _hidl_cb(Status::UNSUPPORTED_OPERATION, 0); @@ -264,32 +317,25 @@ Return<void> Vibrator::perform_1_1(Effect_1_1 effect, EffectStrength es, perform } using Effect_1_2 = ::android::hardware::vibrator::V1_2::Effect; -Return<void> Vibrator::perform_1_2(Effect_1_2 effect, EffectStrength es, perform_1_2_cb _hidl_cb) { +Return<void> Vibrator::perform_1_2(Effect_1_2 effect, EffectStrength es, perform_cb _hidl_cb) { Status status; + int effectId = static_cast<int16_t>(effect); + long playLengthMs; - if (!mSupportEffects) { - _hidl_cb(Status::UNSUPPORTED_OPERATION, 0); - return Void(); - } - - mCurrEffectId = static_cast<int16_t>(effect); - mCurrMagnitude = convertEffectStrength(es); - if (mCurrEffectId < (static_cast<int16_t>(Effect_1_2::CLICK)) || - mCurrEffectId > (static_cast<int16_t>(Effect_1_2::RINGTONE_15)) || - mCurrMagnitude == 0) { + if (effectId < (static_cast<int16_t>(Effect_1_2::CLICK)) || + effectId > (static_cast<int16_t>(Effect_1_2::RINGTONE_15))) { _hidl_cb(Status::UNSUPPORTED_OPERATION, 0); return Void(); } - status = play(-1); + status = ff.playEffect(effectId, es, &playLengthMs); if (status == Status::OK) - _hidl_cb(Status::OK, mPlayLengthMs); + _hidl_cb(Status::OK, playLengthMs); else _hidl_cb(Status::UNSUPPORTED_OPERATION, 0); return Void(); } - } // namespace implementation } // namespace V1_2 } // namespace vibrator diff --git a/1.2/Vibrator_1_2.h b/1.2/Vibrator_1_2.h new file mode 100644 index 0000000..06ccd93 --- /dev/null +++ b/1.2/Vibrator_1_2.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018,2020, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ANDROID_HARDWARE_VIBRATOR_V1_2_VIBRATOR_H +#define ANDROID_HARDWARE_VIBRATOR_V1_2_VIBRATOR_H + +#include <android/hardware/vibrator/1.2/IVibrator.h> +#include <hidl/Status.h> + +namespace android { +namespace hardware { +namespace vibrator { +namespace V1_2 { +namespace implementation { + +using Status = ::android::hardware::vibrator::V1_0::Status; +using EffectStrength = ::android::hardware::vibrator::V1_0::EffectStrength; + +class InputFFDevice { +public: + InputFFDevice(); + Return<Status> playEffect(int effectId, EffectStrength es, long *playLengthMs); + + Return<Status> on(uint32_t timeoutMs); + Return<Status> off(); + Return<bool> supportsAmplitudeControl(); + Return<Status> setAmplitude(uint8_t amplitude); +private: + Return<Status> play(int effectId, uint32_t timeoutMs, long *playLengthMs); + int mVibraFd; + int16_t mCurrAppId; + int16_t mCurrMagnitude; + bool mSupportGain; + bool mSupportEffects; +}; + +class Vibrator : public IVibrator { +public: + class InputFFDevice ff; + Return<Status> on(uint32_t timeoutMs) {return ff.on(timeoutMs);}; + Return<Status> off() {return ff.off();}; + Return<bool> supportsAmplitudeControl() {return ff.supportsAmplitudeControl();}; + Return<Status> setAmplitude(uint8_t amplitude) {return ff.setAmplitude(amplitude);}; + + Return<void> perform(::android::hardware::vibrator::V1_0::Effect effect, EffectStrength strength, perform_cb _hidl_cb) override; + Return<void> perform_1_1(::android::hardware::vibrator::V1_1::Effect_1_1 effect, EffectStrength strength, perform_cb _hidl_cb) override; + Return<void> perform_1_2(::android::hardware::vibrator::V1_2::Effect effect, EffectStrength strength, perform_cb _hidl_cb) override; +}; + +} // namespace implementation +} // namespace V1_2 +} // namespace vibrator +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_VIBRATOR_V1_2_VIBRATOR_H diff --git a/service.cpp b/1.2/service.cpp index cbf8bf6..0f637b8 100644 --- a/service.cpp +++ b/1.2/service.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2018,2020, The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -34,14 +34,7 @@ #include <hidl/HidlSupport.h> #include <hidl/HidlTransportSupport.h> -#include <dirent.h> -#include <string.h> - -#include <log/log.h> -#include <linux/input.h> -#include <sys/ioctl.h> - -#include "Vibrator.h" +#include "Vibrator_1_2.h" using android::hardware::configureRpcThreadpool; using android::hardware::joinRpcThreadpool; @@ -49,66 +42,13 @@ using android::hardware::vibrator::V1_2::IVibrator; using android::hardware::vibrator::V1_2::implementation::Vibrator; using namespace android; -#define test_bit(bit, array) ((array)[(bit)/8] & (1<<((bit)%8))) int main() { - DIR *dp; - struct dirent *dir; - uint8_t ffBitmask[FF_CNT / 8]; - char devicename[PATH_MAX]; - const char *INPUT_DIR = "/dev/input/"; - bool supportGain = false, supportEffects = false; - bool found = false; - int fd, ret, vibraFd = -1; + int ret; configureRpcThreadpool(1, true); - dp = opendir(INPUT_DIR); - if (!dp) { - ALOGE("open %s failed, errno = %d", INPUT_DIR, errno); - return UNKNOWN_ERROR; - } - memset(ffBitmask, 0, sizeof(ffBitmask)); - while ((dir = readdir(dp)) != NULL){ - if (dir->d_name[0] == '.' && - (dir->d_name[1] == '\0' || - (dir->d_name[1] == '.' && dir->d_name[2] == '\0'))) - continue; - - snprintf(devicename, PATH_MAX, "%s%s", INPUT_DIR, dir->d_name); - fd = TEMP_FAILURE_RETRY(open(devicename, O_RDWR)); - if (fd < 0) { - ALOGE("open %s failed, errno = %d", devicename, errno); - continue; - } - - ret = TEMP_FAILURE_RETRY(ioctl(fd, EVIOCGBIT(EV_FF, sizeof(ffBitmask)), ffBitmask)); - if (ret == -1) { - ALOGE("ioctl failed, errno = %d", errno); - close(fd); - continue; - } - - if (test_bit(FF_CONSTANT, ffBitmask) || - test_bit(FF_PERIODIC, ffBitmask)) { - found = true; - vibraFd = fd; - if (test_bit(FF_CUSTOM, ffBitmask)) - supportEffects = true; - if (test_bit(FF_GAIN, ffBitmask)) - supportGain = true; - break; - } - close(fd); - } - closedir(dp); - - if (found) { - sp<IVibrator> vibrator = new Vibrator(vibraFd, supportGain, supportEffects); - ret = vibrator->registerAsService(); - } else { - ALOGE("Can't find vibrator device"); - ret = UNKNOWN_ERROR; - } + sp<IVibrator> vibrator = new Vibrator(); + ret = vibrator->registerAsService(); joinRpcThreadpool(); return ret; diff --git a/vendor.qti.hardware.vibrator@1.2-service.rc b/1.2/vendor.qti.hardware.vibrator@1.2-service.rc index 639d739..639d739 100644 --- a/vendor.qti.hardware.vibrator@1.2-service.rc +++ b/1.2/vendor.qti.hardware.vibrator@1.2-service.rc diff --git a/1.2/vendor.qti.hardware.vibrator@1.2-service.xml b/1.2/vendor.qti.hardware.vibrator@1.2-service.xml new file mode 100644 index 0000000..f5b4ebd --- /dev/null +++ b/1.2/vendor.qti.hardware.vibrator@1.2-service.xml @@ -0,0 +1,38 @@ +<!-- Copyright (c) 2019-2020 The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<manifest version="1.0" type="device"> + <hal format="hidl"> + <name>android.hardware.vibrator</name> + <transport>hwbinder</transport> + <version>1.2</version> + <interface> + <name>IVibrator</name> + <instance>default</instance> + </interface> + </hal> +</manifest> diff --git a/1.3/Android.bp b/1.3/Android.bp new file mode 100644 index 0000000..73878e6 --- /dev/null +++ b/1.3/Android.bp @@ -0,0 +1,26 @@ +Common_CFlags = ["-Wall"] +Common_CFlags += ["-Werror"] + +cc_binary { + name: "vendor.qti.hardware.vibrator@1.3-service", + vendor: true, + relative_install_path: "hw", + init_rc: ["vendor.qti.hardware.vibrator@1.3-service.rc"], + cflags: Common_CFlags, + srcs: [ + "service.cpp", + "Vibrator.cpp", + ], + shared_libs: [ + "libhidlbase", + "libcutils", + "liblog", + "libutils", + "libhardware", + "android.hardware.vibrator@1.3", + "vendor.qti.hardware.vibrator@1.2-impl", + ], + vintf_fragments: [ + "vendor.qti.hardware.vibrator@1.3-service.xml", + ], +} diff --git a/1.3/Vibrator.cpp b/1.3/Vibrator.cpp new file mode 100644 index 0000000..f965107 --- /dev/null +++ b/1.3/Vibrator.cpp @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "vendor.qti.vibrator@1.3-impl" + +#include <hardware/hardware.h> +#include <hardware/vibrator.h> +#include <inttypes.h> +#include <log/log.h> + +#include "Vibrator_1_3.h" + +namespace android { +namespace hardware { +namespace vibrator { +namespace V1_3 { +namespace implementation { + +using android::hardware::vibrator::V1_0::Status; +using android::hardware::vibrator::V1_0::EffectStrength; +using android::hardware::vibrator::V1_3::Effect; + +/** + * Any targets using V1.3 vibrator interface will support + * external control by default + */ +Return<bool> Vibrator::supportsExternalControl() { + return true; +} + +/** + * The existing hardware module would cease current vibration + * and switch to the external control vibration automatically, + * so nothing need to be done in sw, hence return OK directly. + */ +Return<Status> Vibrator::setExternalControl(__attribute__((unused))bool enable) { + return Status::OK; +} + +using Effect_1_0 = ::android::hardware::vibrator::V1_0::Effect; +Return<void> Vibrator::perform(Effect_1_0 effect, EffectStrength es, perform_cb _hidl_cb) { + Status status; + int effectId = static_cast<int16_t>(effect); + long playLengthMs; + + if (effectId < (static_cast<int16_t>(Effect_1_0::CLICK)) || + effectId > (static_cast<int16_t>(Effect_1_0::DOUBLE_CLICK))) { + _hidl_cb(Status::UNSUPPORTED_OPERATION, 0); + return Void(); + } + + status = ff.playEffect(effectId, es, &playLengthMs); + if (status == Status::OK) + _hidl_cb(Status::OK, playLengthMs); + else + _hidl_cb(Status::UNSUPPORTED_OPERATION, 0); + + return Void(); +} + +using Effect_1_1 = ::android::hardware::vibrator::V1_1::Effect_1_1; +Return<void> Vibrator::perform_1_1(Effect_1_1 effect, EffectStrength es, perform_cb _hidl_cb) { + Status status; + int effectId = static_cast<int16_t>(effect); + long playLengthMs; + + if (effectId < (static_cast<int16_t>(Effect_1_1::CLICK)) || + effectId > (static_cast<int16_t>(Effect_1_1::TICK))) { + _hidl_cb(Status::UNSUPPORTED_OPERATION, 0); + return Void(); + } + + status = ff.playEffect(effectId, es, &playLengthMs); + if (status == Status::OK) + _hidl_cb(Status::OK, playLengthMs); + else + _hidl_cb(Status::UNSUPPORTED_OPERATION, 0); + + return Void(); +} + +using Effect_1_2 = ::android::hardware::vibrator::V1_2::Effect; +Return<void> Vibrator::perform_1_2(Effect_1_2 effect, EffectStrength es, perform_cb _hidl_cb) { + Status status; + int effectId = static_cast<int16_t>(effect); + long playLengthMs; + + if (effectId < (static_cast<int16_t>(Effect_1_2::CLICK)) || + effectId > (static_cast<int16_t>(Effect_1_2::RINGTONE_15))) { + _hidl_cb(Status::UNSUPPORTED_OPERATION, 0); + return Void(); + } + + status = ff.playEffect(effectId, es, &playLengthMs); + if (status == Status::OK) + _hidl_cb(Status::OK, playLengthMs); + else + _hidl_cb(Status::UNSUPPORTED_OPERATION, 0); + + return Void(); +} + +using Effect_1_3 = ::android::hardware::vibrator::V1_3::Effect; +Return<void> Vibrator::perform_1_3(Effect_1_3 effect, EffectStrength es, perform_1_3_cb _hidl_cb) { + Status status; + int effectId = static_cast<int16_t>(effect); + long playLengthMs; + + if (effectId < (static_cast<int16_t>(Effect_1_3::CLICK)) || + effectId > (static_cast<int16_t>(Effect_1_3::TEXTURE_TICK))) { + _hidl_cb(Status::UNSUPPORTED_OPERATION, 0); + return Void(); + } + + status = ff.playEffect(effectId, es, &playLengthMs); + if (status == Status::OK) + _hidl_cb(Status::OK, playLengthMs); + else + _hidl_cb(Status::UNSUPPORTED_OPERATION, 0); + + return Void(); +} +} // namespace implementation +} // namespace V1_3 +} // namespace vibrator +} // namespace hardware +} // namespace android diff --git a/1.3/Vibrator_1_3.h b/1.3/Vibrator_1_3.h new file mode 100644 index 0000000..34a15ad --- /dev/null +++ b/1.3/Vibrator_1_3.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018,2020, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ANDROID_HARDWARE_VIBRATOR_V1_3_VIBRATOR_H +#define ANDROID_HARDWARE_VIBRATOR_V1_3_VIBRATOR_H + +#include <android/hardware/vibrator/1.3/IVibrator.h> +#include <hidl/Status.h> + +#include "Vibrator_1_2.h" + +namespace android { +namespace hardware { +namespace vibrator { +namespace V1_3 { +namespace implementation { + +using android::hardware::vibrator::V1_2::implementation::InputFFDevice; +using android::hardware::vibrator::V1_0::Status; +using android::hardware::vibrator::V1_0::EffectStrength; + +class Vibrator : public IVibrator { +public: + class InputFFDevice ff; + Return<Status> on(uint32_t timeoutMs) {return ff.on(timeoutMs);}; + Return<Status> off() {return ff.off();}; + Return<bool> supportsAmplitudeControl() {return ff.supportsAmplitudeControl();}; + Return<Status> setAmplitude(uint8_t amplitude) {return ff.setAmplitude(amplitude);}; + + Return<bool> supportsExternalControl() override; + Return<Status> setExternalControl(bool enable) override; + Return<void> perform(::android::hardware::vibrator::V1_0::Effect effect, EffectStrength strength, perform_cb _hidl_cb) override; + Return<void> perform_1_1(::android::hardware::vibrator::V1_1::Effect_1_1 effect, EffectStrength strength, perform_cb _hidl_cb) override; + Return<void> perform_1_2(::android::hardware::vibrator::V1_2::Effect effect, EffectStrength strength, perform_cb _hidl_cb) override; + Return<void> perform_1_3(::android::hardware::vibrator::V1_3::Effect effect, EffectStrength strength, perform_cb _hidl_cb) override; +}; + +} // namespace implementation +} // namespace V1_3 +} // namespace vibrator +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_VIBRATOR_V1_3_VIBRATOR_H diff --git a/1.3/service.cpp b/1.3/service.cpp new file mode 100644 index 0000000..7b283d0 --- /dev/null +++ b/1.3/service.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018,2020, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "android.hardware.vibrator@1.3-service.qti" + +#include <android/hardware/vibrator/1.3/IVibrator.h> +#include <hidl/LegacySupport.h> +#include <hidl/HidlSupport.h> +#include <hidl/HidlTransportSupport.h> + +#include "Vibrator_1_3.h" + +using android::hardware::configureRpcThreadpool; +using android::hardware::joinRpcThreadpool; +using android::hardware::vibrator::V1_3::IVibrator; +using android::hardware::vibrator::V1_3::implementation::Vibrator; +using namespace android; + +int main() { + int ret; + + configureRpcThreadpool(1, true); + + sp<IVibrator> vibrator = new Vibrator(); + ret = vibrator->registerAsService(); + + joinRpcThreadpool(); + return ret; +} diff --git a/1.3/vendor.qti.hardware.vibrator@1.3-service.rc b/1.3/vendor.qti.hardware.vibrator@1.3-service.rc new file mode 100644 index 0000000..b87c3c1 --- /dev/null +++ b/1.3/vendor.qti.hardware.vibrator@1.3-service.rc @@ -0,0 +1,4 @@ +service vendor.qti.vibrator-1-3 /vendor/bin/hw/vendor.qti.hardware.vibrator@1.3-service + class hal + user system + group system input diff --git a/1.3/vendor.qti.hardware.vibrator@1.3-service.xml b/1.3/vendor.qti.hardware.vibrator@1.3-service.xml new file mode 100644 index 0000000..db5113e --- /dev/null +++ b/1.3/vendor.qti.hardware.vibrator@1.3-service.xml @@ -0,0 +1,38 @@ +<!-- Copyright (c) 2019-2020 The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<manifest version="1.0" type="device"> + <hal format="hidl"> + <name>android.hardware.vibrator</name> + <transport>hwbinder</transport> + <version>1.3</version> + <interface> + <name>IVibrator</name> + <instance>default</instance> + </interface> + </hal> +</manifest> diff --git a/Android.bp b/qmaa/Android.bp index 3e75b7e..3ad7524 100644 --- a/Android.bp +++ b/qmaa/Android.bp @@ -11,19 +11,6 @@ Common_SharedLibs += ["android.hardware.vibrator@1.1"] Common_SharedLibs += ["android.hardware.vibrator@1.2"] cc_binary { - name: "vendor.qti.hardware.vibrator@1.2-service", - relative_install_path: "hw", - init_rc: ["vendor.qti.hardware.vibrator@1.2-service.rc"], - cflags: Common_CFlags, - srcs: [ - "service.cpp", - "Vibrator.cpp", - ], - shared_libs: Common_SharedLibs, - vendor: true, -} - -cc_binary { name: "vendor.qti.hardware.vibrator.qmaa@1.2-service", relative_install_path: "hw", init_rc: ["vendor.qti.hardware.vibrator@1.2-service.rc"], diff --git a/Vibrator.h b/qmaa/Vibrator_qmaa.h index b297a95..b297a95 100644 --- a/Vibrator.h +++ b/qmaa/Vibrator_qmaa.h diff --git a/service_qmaa.cpp b/qmaa/service_qmaa.cpp index 23e0cbc..c9b5bad 100644 --- a/service_qmaa.cpp +++ b/qmaa/service_qmaa.cpp @@ -27,12 +27,12 @@ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#define LOG_TAG "android.hardware.vibrator@1.2-service.qti" +#define LOG_TAG "android.hardware.vibrator@1.2-service.qmaa" #include <hidl/HidlSupport.h> #include <hidl/HidlTransportSupport.h> -#include "Vibrator.h" +#include "Vibrator_qmaa.h" using android::hardware::configureRpcThreadpool; using android::hardware::joinRpcThreadpool; diff --git a/qmaa/vendor.qti.hardware.vibrator@1.2-service.rc b/qmaa/vendor.qti.hardware.vibrator@1.2-service.rc new file mode 100644 index 0000000..639d739 --- /dev/null +++ b/qmaa/vendor.qti.hardware.vibrator@1.2-service.rc @@ -0,0 +1,4 @@ +service vendor.qti.vibrator-1-2 /vendor/bin/hw/vendor.qti.hardware.vibrator@1.2-service + class hal + user system + group system input diff --git a/vibrator-vendor-product.mk b/vibrator-vendor-product.mk index eb63862..60f583a 100644 --- a/vibrator-vendor-product.mk +++ b/vibrator-vendor-product.mk @@ -1,21 +1,21 @@ ifeq ($(call is-board-platform-in-list, msmnile kona lahaina), true) -ENABLE_VIBRATOR := true +QTI_VIBRATOR_HAL_SERVICE := \ + vendor.qti.hardware.vibrator@1.2-service -ifeq ($(TARGET_USES_QMAA),true) -ifneq ($(TARGET_USES_QMAA_OVERRIDE_VIBRATOR),true) -ENABLE_VIBRATOR := false +ifeq ($(call is-board-platform-in-list, lahaina), true) +QTI_VIBRATOR_HAL_SERVICE := \ + vendor.qti.hardware.vibrator@1.3-service endif -endif - -ifeq ($(ENABLE_VIBRATOR),true) -PRODUCT_PACKAGES += \ - vendor.qti.hardware.vibrator@1.2-service -else -PRODUCT_PACKAGES += \ +ifeq ($(TARGET_USES_QMAA),true) +ifeq ($(TARGET_USES_QMAA_OVERRIDE_VIBRATOR),true) +QTI_VIBRATOR_HAL_SERVICE := \ vendor.qti.hardware.vibrator.qmaa@1.2-service endif +endif + +PRODUCT_PACKAGES += $(QTI_VIBRATOR_HAL_SERVICE) PRODUCT_COPY_FILES += \ vendor/qcom/opensource/vibrator/excluded-input-devices.xml:vendor/etc/excluded-input-devices.xml |