Loading services/inputflinger/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -100,6 +100,7 @@ filegroup { "InputListener.cpp", "InputReaderBase.cpp", "InputThread.cpp", "VibrationElement.cpp" ], } Loading services/inputflinger/VibrationElement.cpp 0 → 100644 +67 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "VibrationElement.h" #include <android-base/stringprintf.h> #include <algorithm> #include <cinttypes> using android::base::StringPrintf; namespace android { // The sentinel to use the default amplitude static const int DEFAULT_AMPLITUDE = -1; // The vibration magnitude for the "DEFAULT_AMPLITUDE" magnitude constant. static const uint16_t DEFAULT_MAGNITUDE = 0xc000; void VibrationElement::dump(std::string& dump) const { dump += StringPrintf("[duration=%lldms, channels=[", duration.count()); if (channels.size()) { dump += std::to_string(channels[0]); std::for_each(channels.begin() + 1, channels.end(), [&dump](int channel) { dump += ", "; dump += std::to_string(channel); }); } dump += "]]"; } uint16_t VibrationElement::getChannel(int id) const { if (id >= (int)channels.size()) { return 0; } // android framework uses DEFAULT_AMPLITUDE to signal that the vibration // should use some built-in default value, denoted here as DEFAULT_MAGNITUDE if (channels[id] == DEFAULT_AMPLITUDE) { return DEFAULT_MAGNITUDE; } // convert range [0,255] to [0,65535] (android framework to linux ff ranges) return ((uint16_t)channels[id]) << 8; } bool VibrationElement::isOn() const { return std::any_of(channels.begin(), channels.end(), [](uint16_t channel) { return channel != 0; }); } } // namespace android services/inputflinger/include/InputReaderBase.h +8 −6 Original line number Diff line number Diff line Loading @@ -17,23 +17,24 @@ #ifndef _UI_INPUT_READER_BASE_H #define _UI_INPUT_READER_BASE_H #include "PointerControllerInterface.h" #include <input/DisplayViewport.h> #include <input/Input.h> #include <input/InputDevice.h> #include <input/VelocityControl.h> #include <input/VelocityTracker.h> #include <stddef.h> #include <unistd.h> #include <utils/Errors.h> #include <utils/RefBase.h> #include <stddef.h> #include <unistd.h> #include <optional> #include <set> #include <unordered_map> #include <vector> #include "PointerControllerInterface.h" #include "VibrationElement.h" // Maximum supported size of a vibration pattern. // Must be at least 2. #define MAX_VIBRATE_PATTERN_SIZE 100 Loading @@ -41,6 +42,7 @@ // Maximum allowable delay value in a vibration pattern before // which the delay will be truncated. #define MAX_VIBRATE_PATTERN_DELAY_NSECS (1000000 * 1000000000LL) #define MAX_VIBRATE_PATTERN_DELAY_MSECS (1000000 * 1000LL) namespace android { Loading Loading @@ -104,7 +106,7 @@ public: virtual void requestRefreshConfiguration(uint32_t changes) = 0; /* Controls the vibrator of a particular input device. */ virtual void vibrate(int32_t deviceId, const nsecs_t* pattern, size_t patternSize, virtual void vibrate(int32_t deviceId, const std::vector<VibrationElement>& pattern, ssize_t repeat, int32_t token) = 0; virtual void cancelVibrate(int32_t deviceId, int32_t token) = 0; Loading services/inputflinger/include/VibrationElement.h 0 → 100644 +41 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef _VIBRATION_ELEMENT_H #define _VIBRATION_ELEMENT_H #include <chrono> #include <cstdint> #include <string> #include <vector> namespace android { /* * Describes a rumble effect */ struct VibrationElement { std::chrono::milliseconds duration; std::vector<int> channels; void dump(std::string& dump) const; uint16_t getChannel(int id) const; bool isOn() const; }; } // namespace android #endif // _VIBRATION_ELEMENT_H services/inputflinger/reader/EventHub.cpp +5 −4 Original line number Diff line number Diff line Loading @@ -702,7 +702,7 @@ void EventHub::assignDescriptorLocked(InputDeviceIdentifier& identifier) { identifier.descriptor.c_str()); } void EventHub::vibrate(int32_t deviceId, nsecs_t duration) { void EventHub::vibrate(int32_t deviceId, const VibrationElement& element) { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device != nullptr && device->hasValidFd()) { Loading @@ -710,9 +710,10 @@ void EventHub::vibrate(int32_t deviceId, nsecs_t duration) { memset(&effect, 0, sizeof(effect)); effect.type = FF_RUMBLE; effect.id = device->ffEffectId; effect.u.rumble.strong_magnitude = 0xc000; effect.u.rumble.weak_magnitude = 0xc000; effect.replay.length = (duration + 999999LL) / 1000000LL; // evdev FF_RUMBLE effect only supports two channels of vibration. effect.u.rumble.strong_magnitude = element.getChannel(0); effect.u.rumble.weak_magnitude = element.getChannel(1); effect.replay.length = element.duration.count(); effect.replay.delay = 0; if (ioctl(device->fd, EVIOCSFF, &effect)) { ALOGW("Could not upload force feedback effect to device %s due to error %d.", Loading Loading
services/inputflinger/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -100,6 +100,7 @@ filegroup { "InputListener.cpp", "InputReaderBase.cpp", "InputThread.cpp", "VibrationElement.cpp" ], } Loading
services/inputflinger/VibrationElement.cpp 0 → 100644 +67 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "VibrationElement.h" #include <android-base/stringprintf.h> #include <algorithm> #include <cinttypes> using android::base::StringPrintf; namespace android { // The sentinel to use the default amplitude static const int DEFAULT_AMPLITUDE = -1; // The vibration magnitude for the "DEFAULT_AMPLITUDE" magnitude constant. static const uint16_t DEFAULT_MAGNITUDE = 0xc000; void VibrationElement::dump(std::string& dump) const { dump += StringPrintf("[duration=%lldms, channels=[", duration.count()); if (channels.size()) { dump += std::to_string(channels[0]); std::for_each(channels.begin() + 1, channels.end(), [&dump](int channel) { dump += ", "; dump += std::to_string(channel); }); } dump += "]]"; } uint16_t VibrationElement::getChannel(int id) const { if (id >= (int)channels.size()) { return 0; } // android framework uses DEFAULT_AMPLITUDE to signal that the vibration // should use some built-in default value, denoted here as DEFAULT_MAGNITUDE if (channels[id] == DEFAULT_AMPLITUDE) { return DEFAULT_MAGNITUDE; } // convert range [0,255] to [0,65535] (android framework to linux ff ranges) return ((uint16_t)channels[id]) << 8; } bool VibrationElement::isOn() const { return std::any_of(channels.begin(), channels.end(), [](uint16_t channel) { return channel != 0; }); } } // namespace android
services/inputflinger/include/InputReaderBase.h +8 −6 Original line number Diff line number Diff line Loading @@ -17,23 +17,24 @@ #ifndef _UI_INPUT_READER_BASE_H #define _UI_INPUT_READER_BASE_H #include "PointerControllerInterface.h" #include <input/DisplayViewport.h> #include <input/Input.h> #include <input/InputDevice.h> #include <input/VelocityControl.h> #include <input/VelocityTracker.h> #include <stddef.h> #include <unistd.h> #include <utils/Errors.h> #include <utils/RefBase.h> #include <stddef.h> #include <unistd.h> #include <optional> #include <set> #include <unordered_map> #include <vector> #include "PointerControllerInterface.h" #include "VibrationElement.h" // Maximum supported size of a vibration pattern. // Must be at least 2. #define MAX_VIBRATE_PATTERN_SIZE 100 Loading @@ -41,6 +42,7 @@ // Maximum allowable delay value in a vibration pattern before // which the delay will be truncated. #define MAX_VIBRATE_PATTERN_DELAY_NSECS (1000000 * 1000000000LL) #define MAX_VIBRATE_PATTERN_DELAY_MSECS (1000000 * 1000LL) namespace android { Loading Loading @@ -104,7 +106,7 @@ public: virtual void requestRefreshConfiguration(uint32_t changes) = 0; /* Controls the vibrator of a particular input device. */ virtual void vibrate(int32_t deviceId, const nsecs_t* pattern, size_t patternSize, virtual void vibrate(int32_t deviceId, const std::vector<VibrationElement>& pattern, ssize_t repeat, int32_t token) = 0; virtual void cancelVibrate(int32_t deviceId, int32_t token) = 0; Loading
services/inputflinger/include/VibrationElement.h 0 → 100644 +41 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef _VIBRATION_ELEMENT_H #define _VIBRATION_ELEMENT_H #include <chrono> #include <cstdint> #include <string> #include <vector> namespace android { /* * Describes a rumble effect */ struct VibrationElement { std::chrono::milliseconds duration; std::vector<int> channels; void dump(std::string& dump) const; uint16_t getChannel(int id) const; bool isOn() const; }; } // namespace android #endif // _VIBRATION_ELEMENT_H
services/inputflinger/reader/EventHub.cpp +5 −4 Original line number Diff line number Diff line Loading @@ -702,7 +702,7 @@ void EventHub::assignDescriptorLocked(InputDeviceIdentifier& identifier) { identifier.descriptor.c_str()); } void EventHub::vibrate(int32_t deviceId, nsecs_t duration) { void EventHub::vibrate(int32_t deviceId, const VibrationElement& element) { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device != nullptr && device->hasValidFd()) { Loading @@ -710,9 +710,10 @@ void EventHub::vibrate(int32_t deviceId, nsecs_t duration) { memset(&effect, 0, sizeof(effect)); effect.type = FF_RUMBLE; effect.id = device->ffEffectId; effect.u.rumble.strong_magnitude = 0xc000; effect.u.rumble.weak_magnitude = 0xc000; effect.replay.length = (duration + 999999LL) / 1000000LL; // evdev FF_RUMBLE effect only supports two channels of vibration. effect.u.rumble.strong_magnitude = element.getChannel(0); effect.u.rumble.weak_magnitude = element.getChannel(1); effect.replay.length = element.duration.count(); effect.replay.delay = 0; if (ioctl(device->fd, EVIOCSFF, &effect)) { ALOGW("Could not upload force feedback effect to device %s due to error %d.", Loading