diff options
author | 2020-10-16 12:55:26 -0700 | |
---|---|---|
committer | 2020-12-16 15:42:57 -0800 | |
commit | f59a2f484d4765edd74c9bb3f911f66c4eb7a3f4 (patch) | |
tree | b91d1eb60a4d61bf4a7bc44f2f170633f61b176f | |
parent | ef7705d5695070d62ed58047021af5318d91d494 (diff) |
Add SensorManager support in inputflinger.
Add sensor device, sensor input mapper, sens event dispatcher support
into inputflinger.
Bug: 161634265
Test: atest inputflinger_tests
Change-Id: I2dcb2c35d9dccefc4cd8d939b79cf340931a9410
36 files changed, 1587 insertions, 44 deletions
diff --git a/include/android/input.h b/include/android/input.h index 38af89a31e..b5d399ee09 100644 --- a/include/android/input.h +++ b/include/android/input.h @@ -856,6 +856,8 @@ enum { AINPUT_SOURCE_TOUCH_NAVIGATION = 0x00200000 | AINPUT_SOURCE_CLASS_NONE, /** joystick */ AINPUT_SOURCE_JOYSTICK = 0x01000000 | AINPUT_SOURCE_CLASS_JOYSTICK, + /** sensor */ + AINPUT_SOURCE_SENSOR = 0x02000000 | AINPUT_SOURCE_CLASS_JOYSTICK, /** rotary encoder */ AINPUT_SOURCE_ROTARY_ENCODER = 0x00400000 | AINPUT_SOURCE_CLASS_NONE, diff --git a/include/input/InputDevice.h b/include/input/InputDevice.h index 60638caaab..23692e92d4 100644 --- a/include/input/InputDevice.h +++ b/include/input/InputDevice.h @@ -17,8 +17,10 @@ #ifndef _LIBINPUT_INPUT_DEVICE_H #define _LIBINPUT_INPUT_DEVICE_H +#include <android/sensor.h> #include <input/Input.h> #include <input/KeyCharacterMap.h> +#include <unordered_map> #include <vector> namespace android { @@ -63,6 +65,97 @@ struct InputDeviceIdentifier { std::string getCanonicalName() const; }; +/* Types of input device sensors. Keep sync with core/java/android/hardware/Sensor.java */ +enum class InputDeviceSensorType : int32_t { + ACCELEROMETER = ASENSOR_TYPE_ACCELEROMETER, + MAGNETIC_FIELD = ASENSOR_TYPE_MAGNETIC_FIELD, + ORIENTATION = 3, + GYROSCOPE = ASENSOR_TYPE_GYROSCOPE, + LIGHT = ASENSOR_TYPE_LIGHT, + PRESSURE = ASENSOR_TYPE_PRESSURE, + TEMPERATURE = 7, + PROXIMITY = ASENSOR_TYPE_PROXIMITY, + GRAVITY = ASENSOR_TYPE_GRAVITY, + LINEAR_ACCELERATION = ASENSOR_TYPE_LINEAR_ACCELERATION, + ROTATION_VECTOR = ASENSOR_TYPE_ROTATION_VECTOR, + RELATIVE_HUMIDITY = ASENSOR_TYPE_RELATIVE_HUMIDITY, + AMBIENT_TEMPERATURE = ASENSOR_TYPE_AMBIENT_TEMPERATURE, + MAGNETIC_FIELD_UNCALIBRATED = ASENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED, + GAME_ROTATION_VECTOR = ASENSOR_TYPE_GAME_ROTATION_VECTOR, + GYROSCOPE_UNCALIBRATED = ASENSOR_TYPE_GYROSCOPE_UNCALIBRATED, + SIGNIFICANT_MOTION = ASENSOR_TYPE_SIGNIFICANT_MOTION, +}; + +enum class InputDeviceSensorAccuracy : int32_t { + ACCURACY_NONE = 0, + ACCURACY_LOW = 1, + ACCURACY_MEDIUM = 2, + ACCURACY_HIGH = 3, +}; + +enum class InputDeviceSensorReportingMode : int32_t { + CONTINUOUS = 0, + ON_CHANGE = 1, + ONE_SHOT = 2, + SPECIAL_TRIGGER = 3, +}; + +struct InputDeviceSensorInfo { + explicit InputDeviceSensorInfo(std::string name, std::string vendor, int32_t version, + InputDeviceSensorType type, InputDeviceSensorAccuracy accuracy, + float maxRange, float resolution, float power, int32_t minDelay, + int32_t fifoReservedEventCount, int32_t fifoMaxEventCount, + std::string stringType, int32_t maxDelay, int32_t flags, + int32_t id) + : name(name), + vendor(vendor), + version(version), + type(type), + accuracy(accuracy), + maxRange(maxRange), + resolution(resolution), + power(power), + minDelay(minDelay), + fifoReservedEventCount(fifoReservedEventCount), + fifoMaxEventCount(fifoMaxEventCount), + stringType(stringType), + maxDelay(maxDelay), + flags(flags), + id(id) {} + // Name string of the sensor. + std::string name; + // Vendor string of this sensor. + std::string vendor; + // Version of the sensor's module. + int32_t version; + // Generic type of this sensor. + InputDeviceSensorType type; + // The current accuracy of sensor event. + InputDeviceSensorAccuracy accuracy; + // Maximum range of the sensor in the sensor's unit. + float maxRange; + // Resolution of the sensor in the sensor's unit. + float resolution; + // The power in mA used by this sensor while in use. + float power; + // The minimum delay allowed between two events in microsecond or zero if this sensor only + // returns a value when the data it's measuring changes. + int32_t minDelay; + // Number of events reserved for this sensor in the batch mode FIFO. + int32_t fifoReservedEventCount; + // Maximum number of events of this sensor that could be batched. + int32_t fifoMaxEventCount; + // The type of this sensor as a string. + std::string stringType; + // The delay between two sensor events corresponding to the lowest frequency that this sensor + // supports. + int32_t maxDelay; + // Sensor flags + int32_t flags; + // Sensor id, same as the input device ID it belongs to. + int32_t id; +}; + /* * Describes the characteristics and capabilities of an input device. */ @@ -104,6 +197,7 @@ public: void addMotionRange(int32_t axis, uint32_t source, float min, float max, float flat, float fuzz, float resolution); void addMotionRange(const MotionRange& range); + void addSensorInfo(const InputDeviceSensorInfo& info); inline void setKeyboardType(int32_t keyboardType) { mKeyboardType = keyboardType; } inline int32_t getKeyboardType() const { return mKeyboardType; } @@ -122,10 +216,17 @@ public: inline void setButtonUnderPad(bool hasButton) { mHasButtonUnderPad = hasButton; } inline bool hasButtonUnderPad() const { return mHasButtonUnderPad; } + inline void setHasSensor(bool hasSensor) { mHasSensor = hasSensor; } + inline bool hasSensor() const { return mHasSensor; } + inline const std::vector<MotionRange>& getMotionRanges() const { return mMotionRanges; } + const InputDeviceSensorInfo* getSensorInfo(InputDeviceSensorType type); + + const std::vector<InputDeviceSensorType> getSensorTypes(); + private: int32_t mId; int32_t mGeneration; @@ -139,8 +240,10 @@ private: std::shared_ptr<KeyCharacterMap> mKeyCharacterMap; bool mHasVibrator; bool mHasButtonUnderPad; + bool mHasSensor; std::vector<MotionRange> mMotionRanges; + std::unordered_map<InputDeviceSensorType, InputDeviceSensorInfo> mSensors; }; /* Types of input device configuration files. */ diff --git a/include/input/KeyCharacterMap.h b/include/input/KeyCharacterMap.h index 23f8ddf764..451ca3c6cd 100644 --- a/include/input/KeyCharacterMap.h +++ b/include/input/KeyCharacterMap.h @@ -142,6 +142,8 @@ public: void writeToParcel(Parcel* parcel) const; #endif + bool operator==(const KeyCharacterMap& other) const; + KeyCharacterMap(const KeyCharacterMap& other); virtual ~KeyCharacterMap(); diff --git a/include/input/KeyLayoutMap.h b/include/input/KeyLayoutMap.h index 872dd45c73..b2bd535cbf 100644 --- a/include/input/KeyLayoutMap.h +++ b/include/input/KeyLayoutMap.h @@ -24,6 +24,8 @@ #include <utils/RefBase.h> #include <utils/Tokenizer.h> +#include <input/InputDevice.h> + namespace android { struct AxisInfo { @@ -76,6 +78,8 @@ public: status_t mapAxis(int32_t scanCode, AxisInfo* outAxisInfo) const; const std::string getLoadFileName() const; + // Return pair of sensor type and sensor data index, for the input device abs code + base::Result<std::pair<InputDeviceSensorType, int32_t>> mapSensor(int32_t absCode); virtual ~KeyLayoutMap(); @@ -89,12 +93,17 @@ private: int32_t ledCode; }; + struct Sensor { + InputDeviceSensorType sensorType; + int32_t sensorDataIndex; + }; KeyedVector<int32_t, Key> mKeysByScanCode; KeyedVector<int32_t, Key> mKeysByUsageCode; KeyedVector<int32_t, AxisInfo> mAxes; KeyedVector<int32_t, Led> mLedsByScanCode; KeyedVector<int32_t, Led> mLedsByUsageCode; + std::unordered_map<int32_t, Sensor> mSensorsByAbsCode; std::string mLoadFileName; KeyLayoutMap(); @@ -114,6 +123,7 @@ private: status_t parseKey(); status_t parseAxis(); status_t parseLed(); + status_t parseSensor(); }; }; diff --git a/libs/input/InputDevice.cpp b/libs/input/InputDevice.cpp index 34eba5be7f..2ed441d8b4 100644 --- a/libs/input/InputDevice.cpp +++ b/libs/input/InputDevice.cpp @@ -23,6 +23,7 @@ #include <android-base/stringprintf.h> #include <input/InputDevice.h> #include <input/InputEventLabels.h> +#include <input/NamedEnum.h> using android::base::StringPrintf; @@ -166,7 +167,9 @@ InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) mKeyCharacterMap(other.mKeyCharacterMap), mHasVibrator(other.mHasVibrator), mHasButtonUnderPad(other.mHasButtonUnderPad), - mMotionRanges(other.mMotionRanges) {} + mHasSensor(other.mHasSensor), + mMotionRanges(other.mMotionRanges), + mSensors(other.mSensors) {} InputDeviceInfo::~InputDeviceInfo() { } @@ -185,7 +188,9 @@ void InputDeviceInfo::initialize(int32_t id, int32_t generation, int32_t control mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE; mHasVibrator = false; mHasButtonUnderPad = false; + mHasSensor = false; mMotionRanges.clear(); + mSensors.clear(); } const InputDeviceInfo::MotionRange* InputDeviceInfo::getMotionRange( @@ -214,4 +219,28 @@ void InputDeviceInfo::addMotionRange(const MotionRange& range) { mMotionRanges.push_back(range); } +void InputDeviceInfo::addSensorInfo(const InputDeviceSensorInfo& info) { + if (mSensors.find(info.type) != mSensors.end()) { + ALOGW("Sensor type %s already exists, will be replaced by new sensor added.", + NamedEnum::string(info.type).c_str()); + } + mSensors.insert_or_assign(info.type, info); +} + +const std::vector<InputDeviceSensorType> InputDeviceInfo::getSensorTypes() { + std::vector<InputDeviceSensorType> types; + for (const auto& [type, info] : mSensors) { + types.push_back(type); + } + return types; +} + +const InputDeviceSensorInfo* InputDeviceInfo::getSensorInfo(InputDeviceSensorType type) { + auto it = mSensors.find(type); + if (it == mSensors.end()) { + return nullptr; + } + return &it->second; +} + } // namespace android diff --git a/libs/input/KeyCharacterMap.cpp b/libs/input/KeyCharacterMap.cpp index f5432ad3ee..5666de6624 100644 --- a/libs/input/KeyCharacterMap.cpp +++ b/libs/input/KeyCharacterMap.cpp @@ -103,6 +103,48 @@ KeyCharacterMap::~KeyCharacterMap() { } } +bool KeyCharacterMap::operator==(const KeyCharacterMap& other) const { + if (mType != other.mType) { + return false; + } + if (mKeys.size() != other.mKeys.size() || + mKeysByScanCode.size() != other.mKeysByScanCode.size() || + mKeysByUsageCode.size() != other.mKeysByUsageCode.size()) { + return false; + } + + for (size_t i = 0; i < mKeys.size(); i++) { + if (mKeys.keyAt(i) != other.mKeys.keyAt(i)) { + return false; + } + const Key* key = mKeys.valueAt(i); + const Key* otherKey = other.mKeys.valueAt(i); + if (key->label != otherKey->label || key->number != otherKey->number) { + return false; + } + } + + for (size_t i = 0; i < mKeysByScanCode.size(); i++) { + if (mKeysByScanCode.keyAt(i) != other.mKeysByScanCode.keyAt(i)) { + return false; + } + if (mKeysByScanCode.valueAt(i) != other.mKeysByScanCode.valueAt(i)) { + return false; + } + } + + for (size_t i = 0; i < mKeysByUsageCode.size(); i++) { + if (mKeysByUsageCode.keyAt(i) != other.mKeysByUsageCode.keyAt(i)) { + return false; + } + if (mKeysByUsageCode.valueAt(i) != other.mKeysByUsageCode.valueAt(i)) { + return false; + } + } + + return true; +} + base::Result<std::shared_ptr<KeyCharacterMap>> KeyCharacterMap::load(const std::string& filename, Format format) { Tokenizer* tokenizer; diff --git a/libs/input/KeyLayoutMap.cpp b/libs/input/KeyLayoutMap.cpp index 16ce48aca1..d36e417850 100644 --- a/libs/input/KeyLayoutMap.cpp +++ b/libs/input/KeyLayoutMap.cpp @@ -20,12 +20,13 @@ #include <android/keycodes.h> #include <input/InputEventLabels.h> -#include <input/Keyboard.h> #include <input/KeyLayoutMap.h> -#include <utils/Log.h> +#include <input/Keyboard.h> +#include <input/NamedEnum.h> #include <utils/Errors.h> -#include <utils/Tokenizer.h> +#include <utils/Log.h> #include <utils/Timers.h> +#include <utils/Tokenizer.h> // Enables debug output for the parser. #define DEBUG_PARSER 0 @@ -41,6 +42,26 @@ namespace android { static const char* WHITESPACE = " \t\r"; +#define SENSOR_ENTRY(type) NamedEnum::string(type), type +static const std::unordered_map<std::string, InputDeviceSensorType> SENSOR_LIST = + {{SENSOR_ENTRY(InputDeviceSensorType::ACCELEROMETER)}, + {SENSOR_ENTRY(InputDeviceSensorType::MAGNETIC_FIELD)}, + {SENSOR_ENTRY(InputDeviceSensorType::ORIENTATION)}, + {SENSOR_ENTRY(InputDeviceSensorType::GYROSCOPE)}, + {SENSOR_ENTRY(InputDeviceSensorType::LIGHT)}, + {SENSOR_ENTRY(InputDeviceSensorType::PRESSURE)}, + {SENSOR_ENTRY(InputDeviceSensorType::TEMPERATURE)}, + {SENSOR_ENTRY(InputDeviceSensorType::PROXIMITY)}, + {SENSOR_ENTRY(InputDeviceSensorType::GRAVITY)}, + {SENSOR_ENTRY(InputDeviceSensorType::LINEAR_ACCELERATION)}, + {SENSOR_ENTRY(InputDeviceSensorType::ROTATION_VECTOR)}, + {SENSOR_ENTRY(InputDeviceSensorType::RELATIVE_HUMIDITY)}, + {SENSOR_ENTRY(InputDeviceSensorType::AMBIENT_TEMPERATURE)}, + {SENSOR_ENTRY(InputDeviceSensorType::MAGNETIC_FIELD_UNCALIBRATED)}, + {SENSOR_ENTRY(InputDeviceSensorType::GAME_ROTATION_VECTOR)}, + {SENSOR_ENTRY(InputDeviceSensorType::GYROSCOPE_UNCALIBRATED)}, + {SENSOR_ENTRY(InputDeviceSensorType::SIGNIFICANT_MOTION)}}; + // --- KeyLayoutMap --- KeyLayoutMap::KeyLayoutMap() { @@ -127,6 +148,24 @@ status_t KeyLayoutMap::mapKey(int32_t scanCode, int32_t usageCode, return NO_ERROR; } +// Return pair of sensor type and sensor data index, for the input device abs code +base::Result<std::pair<InputDeviceSensorType, int32_t>> KeyLayoutMap::mapSensor(int32_t absCode) { + auto it = mSensorsByAbsCode.find(absCode); + if (it == mSensorsByAbsCode.end()) { +#if DEBUG_MAPPING + ALOGD("mapSensor: absCode=%d, ~ Failed.", absCode); +#endif + return Errorf("Can't find abs code {}.", absCode); + } + const Sensor& sensor = it->second; + +#if DEBUG_MAPPING + ALOGD("mapSensor: absCode=%d, sensorType=0x%0x, sensorDataIndex=0x%x.", absCode, + NamedEnum::string(sensor.sensorType), sensor.sensorDataIndex); +#endif + return std::make_pair(sensor.sensorType, sensor.sensorDataIndex); +} + const KeyLayoutMap::Key* KeyLayoutMap::getKey(int32_t scanCode, int32_t usageCode) const { if (usageCode) { ssize_t index = mKeysByUsageCode.indexOfKey(usageCode); @@ -242,6 +281,10 @@ status_t KeyLayoutMap::Parser::parse() { mTokenizer->skipDelimiters(WHITESPACE); status_t status = parseLed(); if (status) return status; + } else if (keywordToken == "sensor") { + mTokenizer->skipDelimiters(WHITESPACE); + status_t status = parseSensor(); + if (status) return status; } else { ALOGE("%s: Expected keyword, got '%s'.", mTokenizer->getLocation().string(), keywordToken.string()); @@ -468,4 +511,84 @@ status_t KeyLayoutMap::Parser::parseLed() { map.add(code, led); return NO_ERROR; } + +static std::optional<InputDeviceSensorType> getSensorType(const char* token) { + auto it = SENSOR_LIST.find(std::string(token)); + if (it == SENSOR_LIST.end()) { + return std::nullopt; + } + return it->second; +} + +static std::optional<int32_t> getSensorDataIndex(String8 token) { + std::string tokenStr(token.string()); + if (tokenStr == "X") { + return 0; + } else if (tokenStr == "Y") { + return 1; + } else if (tokenStr == "Z") { + return 2; + } + return std::nullopt; +} + +// Parse sensor type and data index mapping, as below format +// sensor <raw abs> <sensor type> <sensor data index> +// raw abs : the linux abs code of the axis +// sensor type : string name of InputDeviceSensorType +// sensor data index : the data index of sensor, out of [X, Y, Z] +// Examples: +// sensor 0x00 ACCELEROMETER X +// sensor 0x01 ACCELEROMETER Y +// sensor 0x02 ACCELEROMETER Z +// sensor 0x03 GYROSCOPE X +// sensor 0x04 GYROSCOPE Y +// sensor 0x05 GYROSCOPE Z +status_t KeyLayoutMap::Parser::parseSensor() { + String8 codeToken = mTokenizer->nextToken(WHITESPACE); + char* end; + int32_t code = int32_t(strtol(codeToken.string(), &end, 0)); + if (*end) { + ALOGE("%s: Expected sensor %s number, got '%s'.", mTokenizer->getLocation().string(), + "abs code", codeToken.string()); + return BAD_VALUE; + } + + std::unordered_map<int32_t, Sensor>& map = mMap->mSensorsByAbsCode; + if (map.find(code) != map.end()) { + ALOGE("%s: Duplicate entry for sensor %s '%s'.", mTokenizer->getLocation().string(), + "abs code", codeToken.string()); + return BAD_VALUE; + } + + mTokenizer->skipDelimiters(WHITESPACE); + String8 sensorTypeToken = mTokenizer->nextToken(WHITESPACE); + std::optional<InputDeviceSensorType> typeOpt = getSensorType(sensorTypeToken.string()); + if (!typeOpt) { + ALOGE("%s: Expected sensor code label, got '%s'.", mTokenizer->getLocation().string(), + sensorTypeToken.string()); + return BAD_VALUE; + } + InputDeviceSensorType sensorType = typeOpt.value(); + mTokenizer->skipDelimiters(WHITESPACE); + String8 sensorDataIndexToken = mTokenizer->nextToken(WHITESPACE); + std::optional<int32_t> indexOpt = getSensorDataIndex(sensorDataIndexToken); + if (!indexOpt) { + ALOGE("%s: Expected sensor data index label, got '%s'.", mTokenizer->getLocation().string(), + sensorDataIndexToken.string()); + return BAD_VALUE; + } + int32_t sensorDataIndex = indexOpt.value(); + +#if DEBUG_PARSER + ALOGD("Parsed sensor: abs code=%d, sensorType=%d, sensorDataIndex=%d.", code, + NamedEnum::string(sensorType).c_str(), sensorDataIndex); +#endif + + Sensor sensor; + sensor.sensorType = sensorType; + sensor.sensorDataIndex = sensorDataIndex; + map.emplace(code, sensor); + return NO_ERROR; +} }; diff --git a/libs/input/tests/InputDevice_test.cpp b/libs/input/tests/InputDevice_test.cpp index c174ae94a6..e2cf2456ce 100644 --- a/libs/input/tests/InputDevice_test.cpp +++ b/libs/input/tests/InputDevice_test.cpp @@ -14,9 +14,12 @@ * limitations under the License. */ - +#include <binder/Binder.h> +#include <binder/Parcel.h> #include <gtest/gtest.h> #include <input/InputDevice.h> +#include <input/KeyLayoutMap.h> +#include <input/Keyboard.h> namespace android { @@ -31,4 +34,52 @@ TEST(InputDeviceIdentifierTest, getCanonicalName) { ASSERT_EQ(std::string("deviceName-123_version_C_"), identifier.getCanonicalName()); } +class InputDeviceKeyMapTest : public testing::Test { +protected: + void loadKeyLayout(const char* name) { + std::string path = + getInputDeviceConfigurationFilePathByName(name, + InputDeviceConfigurationFileType:: + KEY_LAYOUT); + ASSERT_FALSE(path.empty()); + base::Result<std::shared_ptr<KeyLayoutMap>> ret = KeyLayoutMap::load(path); + ASSERT_TRUE(ret) << "Cannot load KeyLayout at " << path; + mKeyMap.keyLayoutMap = std::move(*ret); + mKeyMap.keyLayoutFile = path; + } + + void loadKeyCharacterMap(const char* name) { + InputDeviceIdentifier identifier; + identifier.name = name; + std::string path = + getInputDeviceConfigurationFilePathByName(identifier.getCanonicalName(), + InputDeviceConfigurationFileType:: + KEY_CHARACTER_MAP); + ASSERT_FALSE(path.empty()) << "KeyCharacterMap for " << name << " not found"; + base::Result<std::shared_ptr<KeyCharacterMap>> ret = + KeyCharacterMap::load(path, KeyCharacterMap::Format::BASE); + ASSERT_TRUE(ret) << "Cannot load KeyCharacterMap at " << path; + mKeyMap.keyCharacterMap = *ret; + mKeyMap.keyCharacterMapFile = path; + } + + virtual void SetUp() override { + loadKeyLayout("Generic"); + loadKeyCharacterMap("Generic"); + } + + virtual void TearDown() override {} + + KeyMap mKeyMap; +}; + +TEST_F(InputDeviceKeyMapTest, keyCharacterMapParcelingTest) { + Parcel parcel; + mKeyMap.keyCharacterMap->writeToParcel(&parcel); + parcel.setDataPosition(0); + std::shared_ptr<KeyCharacterMap> map = KeyCharacterMap::readFromParcel(&parcel); + // Verify the key character map is the same as original + ASSERT_EQ(*map, *mKeyMap.keyCharacterMap); +} + } // namespace android
\ No newline at end of file diff --git a/services/inputflinger/InputClassifier.cpp b/services/inputflinger/InputClassifier.cpp index eafb5ab340..f5f0400995 100644 --- a/services/inputflinger/InputClassifier.cpp +++ b/services/inputflinger/InputClassifier.cpp @@ -391,6 +391,11 @@ void InputClassifier::notifyMotion(const NotifyMotionArgs* args) { mListener->notifyMotion(&newArgs); } +void InputClassifier::notifySensor(const NotifySensorArgs* args) { + // pass through + mListener->notifySensor(args); +} + void InputClassifier::notifySwitch(const NotifySwitchArgs* args) { // pass through mListener->notifySwitch(args); diff --git a/services/inputflinger/InputClassifier.h b/services/inputflinger/InputClassifier.h index 6965940e17..bf10920e61 100644 --- a/services/inputflinger/InputClassifier.h +++ b/services/inputflinger/InputClassifier.h @@ -229,6 +229,7 @@ public: virtual void notifyKey(const NotifyKeyArgs* args) override; virtual void notifyMotion(const NotifyMotionArgs* args) override; virtual void notifySwitch(const NotifySwitchArgs* args) override; + virtual void notifySensor(const NotifySensorArgs* args) override; virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override; void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) override; diff --git a/services/inputflinger/InputListener.cpp b/services/inputflinger/InputListener.cpp index 49a813e82d..4be49b120f 100644 --- a/services/inputflinger/InputListener.cpp +++ b/services/inputflinger/InputListener.cpp @@ -211,6 +211,41 @@ void NotifySwitchArgs::notify(const sp<InputListenerInterface>& listener) const listener->notifySwitch(this); } +// --- NotifySensorArgs --- + +NotifySensorArgs::NotifySensorArgs(int32_t id, nsecs_t eventTime, int32_t deviceId, uint32_t source, + InputDeviceSensorType sensorType, + InputDeviceSensorAccuracy accuracy, bool accuracyChanged, + nsecs_t hwTimestamp, std::vector<float> values) + : NotifyArgs(id, eventTime), + deviceId(deviceId), + source(source), + sensorType(sensorType), + accuracy(accuracy), + accuracyChanged(accuracyChanged), + hwTimestamp(hwTimestamp), + values(std::move(values)) {} + +NotifySensorArgs::NotifySensorArgs(const NotifySensorArgs& other) + : NotifyArgs(other.id, other.eventTime), + deviceId(other.deviceId), + source(other.source), + sensorType(other.sensorType), + accuracy(other.accuracy), + accuracyChanged(other.accuracyChanged), + hwTimestamp(other.hwTimestamp), + values(other.values) {} + +bool NotifySensorArgs::operator==(const NotifySensorArgs rhs) const { + return id == rhs.id && eventTime == rhs.eventTime && sensorType == rhs.sensorType && + accuracy == rhs.accuracy && accuracyChanged == rhs.accuracyChanged && + hwTimestamp == rhs.hwTimestamp && values == rhs.values; +} + +void NotifySensorArgs::notify(const sp<InputListenerInterface>& listener) const { + listener->notifySensor(this); +} + // --- NotifyDeviceResetArgs --- NotifyDeviceResetArgs::NotifyDeviceResetArgs(int32_t id, nsecs_t eventTime, int32_t deviceId) @@ -286,6 +321,11 @@ void QueuedInputListener::notifySwitch(const NotifySwitchArgs* args) { mArgsQueue.push_back(new NotifySwitchArgs(*args)); } +void QueuedInputListener::notifySensor(const NotifySensorArgs* args) { + traceEvent(__func__, args->id); + mArgsQueue.push_back(new NotifySensorArgs(*args)); +} + void QueuedInputListener::notifyDeviceReset(const NotifyDeviceResetArgs* args) { traceEvent(__func__, args->id); mArgsQueue.push_back(new NotifyDeviceResetArgs(*args)); diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp index 7c572b4682..4e55872bc6 100644 --- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp +++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp @@ -66,6 +66,13 @@ private: void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {} + void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType, + InputDeviceSensorAccuracy accuracy, nsecs_t timestamp, + const std::vector<float>& values) override {} + + void notifySensorAccuracy(int32_t deviceId, InputDeviceSensorType sensorType, + InputDeviceSensorAccuracy accuracy) override {} + void notifyUntrustedTouch(const std::string& obscuringPackage) override {} void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override { diff --git a/services/inputflinger/dispatcher/Entry.cpp b/services/inputflinger/dispatcher/Entry.cpp index d8a6548856..f0976b9030 100644 --- a/services/inputflinger/dispatcher/Entry.cpp +++ b/services/inputflinger/dispatcher/Entry.cpp @@ -239,6 +239,41 @@ std::string MotionEntry::getDescription() const { return msg; } +// --- SensorEntry --- + +SensorEntry::SensorEntry(int32_t id, nsecs_t eventTime, int32_t deviceId, uint32_t source, + uint32_t policyFlags, nsecs_t hwTimestamp, + InputDeviceSensorType sensorType, InputDeviceSensorAccuracy accuracy, + bool accuracyChanged, std::vector<float> values) + : EventEntry(id, Type::SENSOR, eventTime, policyFlags), + deviceId(deviceId), + source(source), + sensorType(sensorType), + accuracy(accuracy), + accuracyChanged(accuracyChanged), + hwTimestamp(hwTimestamp), + values(std::move(values)) {} + +SensorEntry::~SensorEntry() {} + +std::string SensorEntry::getDescription() const { + std::string msg; + msg += StringPrintf("SensorEntry(deviceId=%d, source=0x%08x, sensorType=0x%08x, " + "accuracy=0x%08x, hwTimestamp=%" PRId64, + deviceId, source, sensorType, accuracy, hwTimestamp); + + if (!GetBoolProperty("ro.debuggable", false)) { + for (size_t i = 0; i < values.size(); i++) { + if (i > 0) { + msg += ", "; + } + msg += StringPrintf("(%.3f)", values[i]); + } + } + msg += StringPrintf(", policyFlags=0x%08x", policyFlags); + return msg; +} + // --- DispatchEntry --- volatile int32_t DispatchEntry::sNextSeqAtomic; diff --git a/services/inputflinger/dispatcher/Entry.h b/services/inputflinger/dispatcher/Entry.h index fba5514625..3a860f05e0 100644 --- a/services/inputflinger/dispatcher/Entry.h +++ b/services/inputflinger/dispatcher/Entry.h @@ -36,26 +36,10 @@ struct EventEntry { FOCUS, KEY, MOTION, + SENSOR, POINTER_CAPTURE_CHANGED, }; - static const char* typeToString(Type type) { - switch (type) { - case Type::CONFIGURATION_CHANGED: - return "CONFIGURATION_CHANGED"; - case Type::DEVICE_RESET: - return "DEVICE_RESET"; - case Type::FOCUS: - return "FOCUS"; - case Type::KEY: - return "KEY"; - case Type::MOTION: - return "MOTION"; - case Type::POINTER_CAPTURE_CHANGED: - return "POINTER_CAPTURE_CHANGED"; - } - } - int32_t id; Type type; nsecs_t eventTime; @@ -191,6 +175,25 @@ struct MotionEntry : EventEntry { virtual ~MotionEntry(); }; +struct SensorEntry : EventEntry { + int32_t deviceId; + uint32_t source; + InputDeviceSensorType sensorType; + InputDeviceSensorAccuracy accuracy; + bool accuracyChanged; + nsecs_t hwTimestamp; + + std::vector<float> values; + + SensorEntry(int32_t id, nsecs_t eventTime, int32_t deviceId, uint32_t source, + uint32_t policyFlags, nsecs_t hwTimestamp, InputDeviceSensorType sensorType, + InputDeviceSensorAccuracy accuracy, bool accuracyChanged, + std::vector<float> values); + std::string getDescription() const override; + + virtual ~SensorEntry(); +}; + // Tracks the progress of dispatching a particular event to a particular connection. struct DispatchEntry { const uint32_t seq; // unique sequence number, never 0 @@ -257,6 +260,7 @@ struct CommandEntry { sp<Connection> connection; nsecs_t eventTime; std::shared_ptr<KeyEntry> keyEntry; + std::shared_ptr<SensorEntry> sensorEntry; std::shared_ptr<InputApplicationHandle> inputApplicationHandle; std::string reason; int32_t userActivityEventType; diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 6c44a54550..3af33726fd 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -47,8 +47,6 @@ static constexpr bool DEBUG_TOUCH_OCCLUSION = true; // Log debug messages about hover events. #define DEBUG_HOVER 0 -#include "InputDispatcher.h" - #include <android-base/chrono_utils.h> #include <android-base/stringprintf.h> #include <android/os/IInputConstants.h> @@ -73,6 +71,7 @@ static constexpr bool DEBUG_TOUCH_OCCLUSION = true; #include <sstream> #include "Connection.h" +#include "InputDispatcher.h" #define INDENT " " #define INDENT2 " " @@ -758,6 +757,23 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) { done = dispatchMotionLocked(currentTime, motionEntry, &dropReason, nextWakeupTime); break; } + + case EventEntry::Type::SENSOR: { + std::shared_ptr<SensorEntry> sensorEntry = + std::static_pointer_cast<SensorEntry>(mPendingEvent); + if (dropReason == DropReason::NOT_DROPPED && isAppSwitchDue) { + dropReason = DropReason::APP_SWITCH; + } + // Sensor timestamps use SYSTEM_TIME_BOOTTIME time base, so we can't use + // 'currentTime' here, get SYSTEM_TIME_BOOTTIME instead. + nsecs_t bootTime = systemTime(SYSTEM_TIME_BOOTTIME); + if (dropReason == DropReason::NOT_DROPPED && isStaleEvent(bootTime, *sensorEntry)) { + dropReason = DropReason::STALE; + } + dispatchSensorLocked(currentTime, sensorEntry, &dropReason, nextWakeupTime); + done = true; + break; + } } if (done) { @@ -873,6 +889,7 @@ bool InputDispatcher::enqueueInboundEventLocked(std::unique_ptr<EventEntry> newE } case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: + case EventEntry::Type::SENSOR: case EventEntry::Type::POINTER_CAPTURE_CHANGED: { // nothing to do break; @@ -883,7 +900,10 @@ bool InputDispatcher::enqueueInboundEventLocked(std::unique_ptr<EventEntry> newE } void InputDispatcher::addRecentEventLocked(std::shared_ptr<EventEntry> entry) { - mRecentQueue.push_back(entry); + // Do not store sensor event in recent queue to avoid flooding the queue. + if (entry->type != EventEntry::Type::SENSOR) { + mRecentQueue.push_back(entry); + } if (mRecentQueue.size() > RECENT_QUEUE_MAX_SIZE) { mRecentQueue.pop_front(); } @@ -1006,13 +1026,16 @@ void InputDispatcher::dropInboundEventLocked(const EventEntry& entry, DropReason } break; } + case EventEntry::Type::SENSOR: { + break; + } case EventEntry::Type::POINTER_CAPTURE_CHANGED: { break; } case EventEntry::Type::FOCUS: case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: { - LOG_ALWAYS_FATAL("Should not drop %s events", EventEntry::typeToString(entry.type)); + LOG_ALWAYS_FATAL("Should not drop %s events", NamedEnum::string(entry.type).c_str()); break; } } @@ -1365,6 +1388,51 @@ void InputDispatcher::logOutboundKeyDetails(const char* prefix, const KeyEntry& #endif } +void InputDispatcher::doNotifySensorLockedInterruptible(CommandEntry* commandEntry) { + mLock.unlock(); + + const std::shared_ptr<SensorEntry>& entry = commandEntry->sensorEntry; + if (entry->accuracyChanged) { + mPolicy->notifySensorAccuracy(entry->deviceId, entry->sensorType, entry->accuracy); + } + mPolicy->notifySensorEvent(entry->deviceId, entry->sensorType, entry->accuracy, + entry->hwTimestamp, entry->values); + mLock.lock(); +} + +void InputDispatcher::dispatchSensorLocked(nsecs_t currentTime, std::shared_ptr<SensorEntry> entry, + DropReason* dropReason, nsecs_t* nextWakeupTime) { +#if DEBUG_OUTBOUND_EVENT_DETAILS + ALOGD("notifySensorEvent eventTime=%" PRId64 ", hwTimestamp=%" PRId64 ", deviceId=%d, " + "source=0x%x, sensorType=%s", + entry->eventTime, entry->hwTimestamp, entry->deviceId, entry->source, + NamedEnum::string(sensorType).c_str()); +#endif + std::unique_ptr<CommandEntry> commandEntry = + std::make_unique<CommandEntry>(&InputDispatcher::doNotifySensorLockedInterruptible); + commandEntry->sensorEntry = entry; + postCommandLocked(std::move(commandEntry)); +} + +bool InputDispatcher::flushSensor(int deviceId, InputDeviceSensorType sensorType) { +#if DEBUG_OUTBOUND_EVENT_DETAILS + ALOGD("flushSensor deviceId=%d, sensorType=%s", deviceId, + NamedEnum::string(sensorType).c_str()); +#endif + { // acquire lock + std::scoped_lock _l(mLock); + + for (auto it = mInboundQueue.begin(); it != mInboundQueue.end(); it++) { + std::shared_ptr<EventEntry> entry = *it; + if (entry->type == EventEntry::Type::SENSOR) { + it = mInboundQueue.erase(it); + releaseInboundEventLocked(entry); + } + } + } + return true; +} + bool InputDispatcher::dispatchMotionLocked(nsecs_t currentTime, std::shared_ptr<MotionEntry> entry, DropReason* dropReason, nsecs_t* nextWakeupTime) { ATRACE_CALL(); @@ -1553,8 +1621,9 @@ int32_t InputDispatcher::getTargetDisplayId(const EventEntry& entry) { case EventEntry::Type::POINTER_CAPTURE_CHANGED: case EventEntry::Type::FOCUS: case EventEntry::Type::CONFIGURATION_CHANGED: - case EventEntry::Type::DEVICE_RESET: { - ALOGE("%s events do not have a target display", EventEntry::typeToString(entry.type)); + case EventEntry::Type::DEVICE_RESET: + case EventEntry::Type::SENSOR: { + ALOGE("%s events do not have a target display", NamedEnum::string(entry.type).c_str()); return ADISPLAY_ID_NONE; } } @@ -1608,7 +1677,7 @@ InputEventInjectionResult InputDispatcher::findFocusedWindowTargetsLocked( if (focusedWindowHandle == nullptr && focusedApplicationHandle == nullptr) { ALOGI("Dropping %s event because there is no focused window or focused application in " "display %" PRId32 ".", - EventEntry::typeToString(entry.type), displayId); + NamedEnum::string(entry.type).c_str(), displayId); return InputEventInjectionResult::FAILED; } @@ -1633,7 +1702,7 @@ InputEventInjectionResult InputDispatcher::findFocusedWindowTargetsLocked( } else if (currentTime > *mNoFocusedWindowTimeoutTime) { // Already raised ANR. Drop the event ALOGE("Dropping %s event because there is no focused window", - EventEntry::typeToString(entry.type)); + NamedEnum::string(entry.type).c_str()); return InputEventInjectionResult::FAILED; } else { // Still waiting for the focused window @@ -2476,9 +2545,10 @@ void InputDispatcher::pokeUserActivityLocked(const EventEntry& eventEntry) { case EventEntry::Type::FOCUS: case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: + case EventEntry::Type::SENSOR: case EventEntry::Type::POINTER_CAPTURE_CHANGED: { LOG_ALWAYS_FATAL("%s events are not user activity", - EventEntry::typeToString(eventEntry.type)); + NamedEnum::string(eventEntry.type).c_str()); break; } } @@ -2522,7 +2592,7 @@ void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime, if (inputTarget.flags & InputTarget::FLAG_SPLIT) { LOG_ALWAYS_FATAL_IF(eventEntry->type != EventEntry::Type::MOTION, "Entry type %s should not have FLAG_SPLIT", - EventEntry::typeToString(eventEntry->type)); + NamedEnum::string(eventEntry->type).c_str()); const MotionEntry& originalMotionEntry = static_cast<const MotionEntry&>(*eventEntry); if (inputTarget.pointerIds.count() != originalMotionEntry.pointerCount) { @@ -2692,10 +2762,14 @@ void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connectio case EventEntry::Type::POINTER_CAPTURE_CHANGED: { break; } + case EventEntry::Type::SENSOR: { + LOG_ALWAYS_FATAL("SENSOR events should not go to apps via input channel"); + break; + } case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: { LOG_ALWAYS_FATAL("%s events should not go to apps", - EventEntry::typeToString(newEntry.type)); + NamedEnum::string(newEntry.type).c_str()); break; } } @@ -2913,9 +2987,10 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, } case EventEntry::Type::CONFIGURATION_CHANGED: - case EventEntry::Type::DEVICE_RESET: { + case EventEntry::Type::DEVICE_RESET: + case EventEntry::Type::SENSOR: { LOG_ALWAYS_FATAL("Should never start dispatch cycles for %s events", - EventEntry::typeToString(eventEntry.type)); + NamedEnum::string(eventEntry.type).c_str()); return; } } @@ -3209,13 +3284,14 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked( case EventEntry::Type::FOCUS: case EventEntry::Type::POINTER_CAPTURE_CHANGED: { LOG_ALWAYS_FATAL("Canceling %s events is not supported", - EventEntry::typeToString(cancelationEventEntry->type)); + NamedEnum::string(cancelationEventEntry->type).c_str()); break; } case EventEntry::Type::CONFIGURATION_CHANGED: - case EventEntry::Type::DEVICE_RESET: { + case EventEntry::Type::DEVICE_RESET: + case EventEntry::Type::SENSOR: { LOG_ALWAYS_FATAL("%s event should not be found inside Connections's queue", - EventEntry::typeToString(cancelationEventEntry->type)); + NamedEnum::string(cancelationEventEntry->type).c_str()); break; } } @@ -3270,9 +3346,10 @@ void InputDispatcher::synthesizePointerDownEventsForConnectionLocked( case EventEntry::Type::FOCUS: case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: - case EventEntry::Type::POINTER_CAPTURE_CHANGED: { + case EventEntry::Type::POINTER_CAPTURE_CHANGED: + case EventEntry::Type::SENSOR: { LOG_ALWAYS_FATAL("%s event should not be found inside Connections's queue", - EventEntry::typeToString(downEventEntry->type)); + NamedEnum::string(downEventEntry->type).c_str()); break; } } @@ -3605,6 +3682,34 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) { } } +void InputDispatcher::notifySensor(const NotifySensorArgs* args) { +#if DEBUG_INBOUND_EVENT_DETAILS + ALOGD("notifySensor - id=%" PRIx32 " eventTime=%" PRId64 ", deviceId=%d, source=0x%x, " + " sensorType=%s", + args->id, args->eventTime, args->deviceId, args->source, + NamedEnum::string(args->sensorType).c_str()); +#endif + + bool needWake; + { // acquire lock + mLock.lock(); + + // Just enqueue a new sensor event. + std::unique_ptr<SensorEntry> newEntry = + std::make_unique<SensorEntry>(args->id, args->eventTime, args->deviceId, + args->source, 0 /* policyFlags*/, args->hwTimestamp, + args->sensorType, args->accuracy, + args->accuracyChanged, args->values); + + needWake = enqueueInboundEventLocked(std::move(newEntry)); + mLock.unlock(); + } // release lock + + if (needWake) { + mLooper->wake(); + } +} + bool InputDispatcher::shouldSendMotionToInputFilterLocked(const NotifyMotionArgs* args) { return mInputFilterEnabled; } diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h index 5d37645e40..3004701424 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.h +++ b/services/inputflinger/dispatcher/InputDispatcher.h @@ -94,6 +94,7 @@ public: virtual void notifyKey(const NotifyKeyArgs* args) override; virtual void notifyMotion(const NotifyMotionArgs* args) override; virtual void notifySwitch(const NotifySwitchArgs* args) override; + virtual void notifySensor(const NotifySensorArgs* args) override; virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override; virtual void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) override; @@ -128,6 +129,7 @@ public: virtual status_t removeInputChannel(const sp<IBinder>& connectionToken) override; virtual status_t pilferPointers(const sp<IBinder>& token) override; virtual void requestPointerCapture(const sp<IBinder>& windowToken, bool enabled) override; + virtual bool flushSensor(int deviceId, InputDeviceSensorType sensorType) override; std::array<uint8_t, 32> sign(const VerifiedInputEvent& event) const; @@ -392,7 +394,8 @@ private: DropReason& dropReason) REQUIRES(mLock); void dispatchEventLocked(nsecs_t currentTime, std::shared_ptr<EventEntry> entry, const std::vector<InputTarget>& inputTargets) REQUIRES(mLock); - + void dispatchSensorLocked(nsecs_t currentTime, std::shared_ptr<SensorEntry> entry, + DropReason* dropReason, nsecs_t* nextWakeupTime) REQUIRES(mLock); void logOutboundKeyDetails(const char* prefix, const KeyEntry& entry); void logOutboundMotionDetails(const char* prefix, const MotionEntry& entry); @@ -592,6 +595,7 @@ private: REQUIRES(mLock); void doNotifyConnectionResponsiveLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); + void doNotifySensorLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); void doNotifyUntrustedTouchLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); void doInterceptKeyBeforeDispatchingLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); diff --git a/services/inputflinger/dispatcher/InputState.cpp b/services/inputflinger/dispatcher/InputState.cpp index 1656a21b41..3bb0bc995c 100644 --- a/services/inputflinger/dispatcher/InputState.cpp +++ b/services/inputflinger/dispatcher/InputState.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#include "input/InputDevice.h" + #include "InputState.h" #include "InputDispatcher.h" diff --git a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h index 2909d6940d..6e76c92b72 100644 --- a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h +++ b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h @@ -25,6 +25,7 @@ #include <android/os/InputEventInjectionResult.h> #include <android/os/InputEventInjectionSync.h> #include <input/InputApplication.h> +#include <input/InputDevice.h> #include <input/InputTransport.h> #include <input/InputWindow.h> #include <unordered_map> @@ -193,6 +194,11 @@ public: * InputDispatcher is the source of truth of Pointer Capture. */ virtual void requestPointerCapture(const sp<IBinder>& windowToken, bool enabled) = 0; + /* Flush input device motion sensor. + * + * Returns true on success. + */ + virtual bool flushSensor(int deviceId, InputDeviceSensorType sensorType) = 0; }; } // namespace android diff --git a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h index c1821ab10f..d9ec020a2b 100644 --- a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h +++ b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h @@ -68,6 +68,11 @@ public: /* Notifies the system that an input channel is unrecoverably broken. */ virtual void notifyInputChannelBroken(const sp<IBinder>& token) = 0; virtual void notifyFocusChanged(const sp<IBinder>& oldToken, const sp<IBinder>& newToken) = 0; + virtual void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType, + InputDeviceSensorAccuracy accuracy, nsecs_t timestamp, + const std::vector<float>& values) = 0; + virtual void notifySensorAccuracy(int32_t deviceId, InputDeviceSensorType sensorType, + InputDeviceSensorAccuracy accuracy) = 0; /* Notifies the system that an untrusted touch occurred. */ virtual void notifyUntrustedTouch(const std::string& obscuringPackage) = 0; diff --git a/services/inputflinger/include/InputListener.h b/services/inputflinger/include/InputListener.h index 58eb91597b..11f726d50c 100644 --- a/services/inputflinger/include/InputListener.h +++ b/services/inputflinger/include/InputListener.h @@ -20,6 +20,7 @@ #include <vector> #include <input/Input.h> +#include <input/InputDevice.h> #include <input/TouchVideoFrame.h> #include <utils/RefBase.h> @@ -141,6 +142,30 @@ struct NotifyMotionArgs : public NotifyArgs { virtual void notify(const sp<InputListenerInterface>& listener) const; }; +/* Describes a sensor event. */ +struct NotifySensorArgs : public NotifyArgs { + int32_t deviceId; + uint32_t source; + InputDeviceSensorType sensorType; + InputDeviceSensorAccuracy accuracy; + bool accuracyChanged; + nsecs_t hwTimestamp; + std::vector<float> values; + + inline NotifySensorArgs() {} + + NotifySensorArgs(int32_t id, nsecs_t eventTime, int32_t deviceId, uint32_t source, + InputDeviceSensorType sensorType, InputDeviceSensorAccuracy accuracy, + bool accuracyChanged, nsecs_t hwTimestamp, std::vector<float> values); + + NotifySensorArgs(const NotifySensorArgs& other); + + bool operator==(const NotifySensorArgs rhs) const; + + ~NotifySensorArgs() override {} + + void notify(const sp<InputListenerInterface>& listener) const override; +}; /* Describes a switch event. */ struct NotifySwitchArgs : public NotifyArgs { @@ -211,6 +236,7 @@ public: virtual void notifyKey(const NotifyKeyArgs* args) = 0; virtual void notifyMotion(const NotifyMotionArgs* args) = 0; virtual void notifySwitch(const NotifySwitchArgs* args) = 0; + virtual void notifySensor(const NotifySensorArgs* args) = 0; virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) = 0; virtual void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) = 0; }; @@ -231,6 +257,7 @@ public: virtual void notifyKey(const NotifyKeyArgs* args) override; virtual void notifyMotion(const NotifyMotionArgs* args) override; virtual void notifySwitch(const NotifySwitchArgs* args) override; + virtual void notifySensor(const NotifySensorArgs* args) override; virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override; void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) override; diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h index 6cce8ecc7b..ea9b48368e 100644 --- a/services/inputflinger/include/InputReaderBase.h +++ b/services/inputflinger/include/InputReaderBase.h @@ -111,6 +111,17 @@ public: /* Return true if the device can send input events to the specified display. */ virtual bool canDispatchToDisplay(int32_t deviceId, int32_t displayId) = 0; + + /* Enable sensor in input reader mapper. */ + virtual bool enableSensor(int32_t deviceId, InputDeviceSensorType sensorType, + std::chrono::microseconds samplingPeriod, + std::chrono::microseconds maxBatchReportLatency) = 0; + + /* Disable sensor in input reader mapper. */ + virtual void disableSensor(int32_t deviceId, InputDeviceSensorType sensorType) = 0; + + /* Flush sensor data in input reader mapper. */ + virtual void flushSensor(int32_t deviceId, InputDeviceSensorType sensorType) = 0; }; // --- InputReaderConfiguration --- diff --git a/services/inputflinger/reader/Android.bp b/services/inputflinger/reader/Android.bp index 0ccada94e4..abda4ef45c 100644 --- a/services/inputflinger/reader/Android.bp +++ b/services/inputflinger/reader/Android.bp @@ -37,6 +37,7 @@ filegroup { "mapper/KeyboardInputMapper.cpp", "mapper/MultiTouchInputMapper.cpp", "mapper/RotaryEncoderInputMapper.cpp", + "mapper/SensorInputMapper.cpp", "mapper/SingleTouchInputMapper.cpp", "mapper/SwitchInputMapper.cpp", "mapper/TouchInputMapper.cpp", diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp index f864c0e5b6..b97ff909d6 100644 --- a/services/inputflinger/reader/EventHub.cpp +++ b/services/inputflinger/reader/EventHub.cpp @@ -157,6 +157,18 @@ Flags<InputDeviceClass> getAbsAxisUsage(int32_t axis, Flags<InputDeviceClass> de } } + if (deviceClasses.test(InputDeviceClass::SENSOR)) { + switch (axis) { + case ABS_X: + case ABS_Y: + case ABS_Z: + case ABS_RX: + case ABS_RY: + case ABS_RZ: + return InputDeviceClass::SENSOR; + } + } + // External stylus gets the pressure axis if (deviceClasses.test(InputDeviceClass::EXTERNAL_STYLUS)) { if (axis == ABS_PRESSURE) { @@ -250,6 +262,11 @@ void EventHub::Device::configureFd() { // uses the timestamps extensively and assumes they were recorded using the monotonic // clock. int clockId = CLOCK_MONOTONIC; + if (classes.test(InputDeviceClass::SENSOR)) { + // Each new sensor event should use the same time base as + // SystemClock.elapsedRealtimeNanos(). + clockId = CLOCK_BOOTTIME; + } bool usingClockIoctl = !ioctl(fd, EVIOCSCLOCKID, &clockId); ALOGI("usingClockIoctl=%s", toString(usingClockIoctl)); } @@ -550,6 +567,15 @@ bool EventHub::hasInputProperty(int32_t deviceId, int property) const { : false; } +bool EventHub::hasMscEvent(int32_t deviceId, int mscEvent) const { + std::scoped_lock _l(mLock); + + Device* device = getDeviceLocked(deviceId); + return mscEvent >= 0 && mscEvent <= MSC_MAX && device != nullptr + ? device->mscBitmask.test(mscEvent) + : false; +} + int32_t EventHub::getScanCodeState(int32_t deviceId, int32_t scanCode) const { if (scanCode >= 0 && scanCode <= KEY_MAX) { std::scoped_lock _l(mLock); @@ -705,6 +731,17 @@ status_t EventHub::mapAxis(int32_t deviceId, int32_t scanCode, AxisInfo* outAxis return NAME_NOT_FOUND; } +base::Result<std::pair<InputDeviceSensorType, int32_t>> EventHub::mapSensor(int32_t deviceId, + int32_t absCode) { + std::scoped_lock _l(mLock); + Device* device = getDeviceLocked(deviceId); + + if (device != nullptr && device->keyMap.haveKeyLayout()) { + return device->keyMap.keyLayoutMap->mapSensor(absCode); + } + return Errorf("Device not found or device has no key layout."); +} + void EventHub::setExcludedDevices(const std::vector<std::string>& devices) { std::scoped_lock _l(mLock); @@ -1405,6 +1442,7 @@ status_t EventHub::openDeviceLocked(const std::string& devicePath) { device->readDeviceBitMask(EVIOCGBIT(EV_SW, 0), device->swBitmask); device->readDeviceBitMask(EVIOCGBIT(EV_LED, 0), device->ledBitmask); device->readDeviceBitMask(EVIOCGBIT(EV_FF, 0), device->ffBitmask); + device->readDeviceBitMask(EVIOCGBIT(EV_MSC, 0), device->mscBitmask); device->readDeviceBitMask(EVIOCGPROP(0), device->propBitmask); // See if this is a keyboard. Ignore everything in the button range except for @@ -1469,6 +1507,11 @@ status_t EventHub::openDeviceLocked(const std::string& devicePath) { } } + // Check whether this device is an accelerometer. + if (device->propBitmask.test(INPUT_PROP_ACCELEROMETER)) { + device->classes |= InputDeviceClass::SENSOR; + } + // Check whether this device has switches. for (int i = 0; i <= SW_MAX; i++) { if (device->swBitmask.test(i)) { @@ -1493,9 +1536,11 @@ status_t EventHub::openDeviceLocked(const std::string& devicePath) { } // Load the key map. - // We need to do this for joysticks too because the key layout may specify axes. + // We need to do this for joysticks too because the key layout may specify axes, and for + // sensor as well because the key layout may specify the axes to sensor data mapping. status_t keyMapStatus = NAME_NOT_FOUND; - if (device->classes.any(InputDeviceClass::KEYBOARD | InputDeviceClass::JOYSTICK)) { + if (device->classes.any(InputDeviceClass::KEYBOARD | InputDeviceClass::JOYSTICK | + InputDeviceClass::SENSOR)) { // Load the keymap for the device. keyMapStatus = device->loadKeyMapLocked(); } diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp index d25d64a92c..ac72ac4189 100644 --- a/services/inputflinger/reader/InputDevice.cpp +++ b/services/inputflinger/reader/InputDevice.cpp @@ -28,6 +28,7 @@ #include "KeyboardInputMapper.h" #include "MultiTouchInputMapper.h" #include "RotaryEncoderInputMapper.h" +#include "SensorInputMapper.h" #include "SingleTouchInputMapper.h" #include "SwitchInputMapper.h" #include "VibratorInputMapper.h" @@ -196,6 +197,11 @@ void InputDevice::addEventHubDevice(int32_t eventHubId, bool populateMappers) { mappers.push_back(std::make_unique<JoystickInputMapper>(*contextPtr)); } + // Motion sensor enabled devices. + if (classes.test(InputDeviceClass::SENSOR)) { + mappers.push_back(std::make_unique<SensorInputMapper>(*contextPtr)); + } + // External stylus-like devices. if (classes.test(InputDeviceClass::EXTERNAL_STYLUS)) { mappers.push_back(std::make_unique<ExternalStylusInputMapper>(*contextPtr)); @@ -460,6 +466,25 @@ std::vector<int32_t> InputDevice::getVibratorIds() { return vibrators; } +bool InputDevice::enableSensor(InputDeviceSensorType sensorType, + std::chrono::microseconds samplingPeriod, + std::chrono::microseconds maxBatchReportLatency) { + bool success = true; + for_each_mapper( + [&success, sensorType, samplingPeriod, maxBatchReportLatency](InputMapper& mapper) { + success &= mapper.enableSensor(sensorType, samplingPeriod, maxBatchReportLatency); + }); + return success; +} + +void InputDevice::disableSensor(InputDeviceSensorType sensorType) { + for_each_mapper([sensorType](InputMapper& mapper) { mapper.disableSensor(sensorType); }); +} + +void InputDevice::flushSensor(InputDeviceSensorType sensorType) { + for_each_mapper([sensorType](InputMapper& mapper) { mapper.flushSensor(sensorType); }); +} + void InputDevice::cancelTouch(nsecs_t when) { for_each_mapper([when](InputMapper& mapper) { mapper.cancelTouch(when); }); } diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp index a6b5e2deb8..be21ace221 100644 --- a/services/inputflinger/reader/InputReader.cpp +++ b/services/inputflinger/reader/InputReader.cpp @@ -220,6 +220,11 @@ void InputReader::addDeviceLocked(nsecs_t when, int32_t eventHubId) { if (device->getClasses().test(InputDeviceClass::EXTERNAL_STYLUS)) { notifyExternalStylusPresenceChangedLocked(); } + + // Sensor input device is noisy, to save power disable it by default. + if (device->getClasses().test(InputDeviceClass::SENSOR)) { + mEventHub->disableDevice(eventHubId); + } } void InputReader::removeDeviceLocked(nsecs_t when, int32_t eventHubId) { @@ -639,6 +644,36 @@ std::vector<int32_t> InputReader::getVibratorIds(int32_t deviceId) { return {}; } +void InputReader::disableSensor(int32_t deviceId, InputDeviceSensorType sensorType) { + std::scoped_lock _l(mLock); + + InputDevice* device = findInputDeviceLocked(deviceId); + if (device) { + device->disableSensor(sensorType); + } +} + +bool InputReader::enableSensor(int32_t deviceId, InputDeviceSensorType sensorType, + std::chrono::microseconds samplingPeriod, + std::chrono::microseconds maxBatchReportLatency) { + std::scoped_lock _l(mLock); + + InputDevice* device = findInputDeviceLocked(deviceId); + if (device) { + return device->enableSensor(sensorType, samplingPeriod, maxBatchReportLatency); + } + return false; +} + +void InputReader::flushSensor(int32_t deviceId, InputDeviceSensorType sensorType) { + std::scoped_lock _l(mLock); + + InputDevice* device = findInputDeviceLocked(deviceId); + if (device) { + device->flushSensor(sensorType); + } +} + bool InputReader::isInputDeviceEnabled(int32_t deviceId) { std::scoped_lock _l(mLock); diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h index 9e38d0a72a..2cea01776a 100644 --- a/services/inputflinger/reader/include/EventHub.h +++ b/services/inputflinger/reader/include/EventHub.h @@ -118,6 +118,9 @@ enum class InputDeviceClass : uint32_t { /* The input device has a rotary encoder */ ROTARY_ENCODER = 0x00001000, + /* The input device has a sensor like accelerometer, gyro, etc */ + SENSOR = 0x00002000, + /* The input device is virtual (not a real device, not part of UI configuration). */ VIRTUAL = 0x40000000, @@ -177,6 +180,8 @@ public: virtual bool hasInputProperty(int32_t deviceId, int property) const = 0; + virtual bool hasMscEvent(int32_t deviceId, int mscEvent) const = 0; + virtual status_t mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, int32_t metaState, int32_t* outKeycode, int32_t* outMetaState, uint32_t* outFlags) const = 0; @@ -201,6 +206,8 @@ public: */ virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) = 0; virtual std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) = 0; + virtual base::Result<std::pair<InputDeviceSensorType, int32_t>> mapSensor(int32_t deviceId, + int32_t absCode) = 0; /* * Query current input state. @@ -346,6 +353,8 @@ public: bool hasInputProperty(int32_t deviceId, int property) const override final; + bool hasMscEvent(int32_t deviceId, int mscEvent) const override final; + status_t mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, int32_t metaState, int32_t* outKeycode, int32_t* outMetaState, uint32_t* outFlags) const override final; @@ -353,6 +362,9 @@ public: status_t mapAxis(int32_t deviceId, int32_t scanCode, AxisInfo* outAxisInfo) const override final; + base::Result<std::pair<InputDeviceSensorType, int32_t>> mapSensor( + int32_t deviceId, int32_t absCode) override final; + void setExcludedDevices(const std::vector<std::string>& devices) override final; int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const override final; @@ -420,6 +432,7 @@ private: BitArray<LED_MAX> ledBitmask; BitArray<FF_MAX> ffBitmask; BitArray<INPUT_PROP_MAX> propBitmask; + BitArray<MSC_MAX> mscBitmask; std::string configurationFile; std::unique_ptr<PropertyMap> configuration; diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h index 8b14b062cd..5af76b7a71 100644 --- a/services/inputflinger/reader/include/InputDevice.h +++ b/services/inputflinger/reader/include/InputDevice.h @@ -87,6 +87,10 @@ public: bool isVibrating(); std::vector<int32_t> getVibratorIds(); void cancelTouch(nsecs_t when); + bool enableSensor(InputDeviceSensorType sensorType, std::chrono::microseconds samplingPeriod, + std::chrono::microseconds maxBatchReportLatency); + void disableSensor(InputDeviceSensorType sensorType); + void flushSensor(InputDeviceSensorType sensorType); int32_t getMetaState(); void updateMetaState(int32_t keyCode); @@ -229,9 +233,12 @@ public: inline bool hasRelativeAxis(int32_t code) const { return mEventHub->hasRelativeAxis(mId, code); } - inline bool hasInputProperty(int property) const { + inline bool hasInputProperty(int32_t property) const { return mEventHub->hasInputProperty(mId, property); } + + inline bool hasMscEvent(int mscEvent) const { return mEventHub->hasMscEvent(mId, mscEvent); } + inline status_t mapKey(int32_t scanCode, int32_t usageCode, int32_t metaState, int32_t* outKeycode, int32_t* outMetaState, uint32_t* outFlags) const { return mEventHub->mapKey(mId, scanCode, usageCode, metaState, outKeycode, outMetaState, @@ -240,6 +247,10 @@ public: inline status_t mapAxis(int32_t scanCode, AxisInfo* outAxisInfo) const { return mEventHub->mapAxis(mId, scanCode, outAxisInfo); } + inline base::Result<std::pair<InputDeviceSensorType, int32_t>> mapSensor(int32_t absCode) { + return mEventHub->mapSensor(mId, absCode); + } + inline std::vector<TouchVideoFrame> getVideoFrames() { return mEventHub->getVideoFrames(mId); } inline int32_t getScanCodeState(int32_t scanCode) const { return mEventHub->getScanCodeState(mId, scanCode); diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h index b16b86caaa..48d4596383 100644 --- a/services/inputflinger/reader/include/InputReader.h +++ b/services/inputflinger/reader/include/InputReader.h @@ -87,6 +87,14 @@ public: bool canDispatchToDisplay(int32_t deviceId, int32_t displayId) override; + bool enableSensor(int32_t deviceId, InputDeviceSensorType sensorType, + std::chrono::microseconds samplingPeriod, + std::chrono::microseconds maxBatchReportLatency) override; + + void disableSensor(int32_t deviceId, InputDeviceSensorType sensorType) override; + + void flushSensor(int32_t deviceId, InputDeviceSensorType sensorType) override; + protected: // These members are protected so they can be instrumented by test cases. virtual std::shared_ptr<InputDevice> createDeviceLocked(int32_t deviceId, diff --git a/services/inputflinger/reader/mapper/InputMapper.cpp b/services/inputflinger/reader/mapper/InputMapper.cpp index 913cef72bb..1ce54ae2dd 100644 --- a/services/inputflinger/reader/mapper/InputMapper.cpp +++ b/services/inputflinger/reader/mapper/InputMapper.cpp @@ -70,6 +70,16 @@ std::vector<int32_t> InputMapper::getVibratorIds() { void InputMapper::cancelTouch(nsecs_t when) {} +bool InputMapper::enableSensor(InputDeviceSensorType sensorType, + std::chrono::microseconds samplingPeriod, + std::chrono::microseconds maxBatchReportLatency) { + return true; +} + +void InputMapper::disableSensor(InputDeviceSensorType sensorType) {} + +void InputMapper::flushSensor(InputDeviceSensorType sensorType) {} + int32_t InputMapper::getMetaState() { return 0; } diff --git a/services/inputflinger/reader/mapper/InputMapper.h b/services/inputflinger/reader/mapper/InputMapper.h index 088dbd8615..bd64d8d0a8 100644 --- a/services/inputflinger/reader/mapper/InputMapper.h +++ b/services/inputflinger/reader/mapper/InputMapper.h @@ -68,6 +68,11 @@ public: virtual bool isVibrating(); virtual std::vector<int32_t> getVibratorIds(); virtual void cancelTouch(nsecs_t when); + virtual bool enableSensor(InputDeviceSensorType sensorType, + std::chrono::microseconds samplingPeriod, + std::chrono::microseconds maxBatchReportLatency); + virtual void disableSensor(InputDeviceSensorType sensorType); + virtual void flushSensor(InputDeviceSensorType sensorType); virtual int32_t getMetaState(); virtual void updateMetaState(int32_t keyCode); diff --git a/services/inputflinger/reader/mapper/SensorInputMapper.cpp b/services/inputflinger/reader/mapper/SensorInputMapper.cpp new file mode 100644 index 0000000000..7d97014f55 --- /dev/null +++ b/services/inputflinger/reader/mapper/SensorInputMapper.cpp @@ -0,0 +1,421 @@ +/* + * 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 <locale> + +#include "../Macros.h" + +#include "SensorInputMapper.h" + +// Log detailed debug messages about each sensor event notification to the dispatcher. +constexpr bool DEBUG_SENSOR_EVENT_DETAILS = false; + +namespace android { + +// Mask for the LSB 2nd, 3rd and fourth bits. +constexpr int REPORTING_MODE_MASK = 0xE; +constexpr int REPORTING_MODE_SHIFT = 1; +constexpr float GRAVITY_MS2_UNIT = 9.80665f; +constexpr float DEGREE_RADIAN_UNIT = 0.0174533f; + +/* Convert the sensor data from Linux to Android + * Linux accelerometer unit is per g, Android unit is m/s^2 + * Linux gyroscope unit is degree/second, Android unit is radians/second + */ +static void convertFromLinuxToAndroid(std::vector<float>& values, + InputDeviceSensorType sensorType) { + for (size_t i = 0; i < values.size(); i++) { + switch (sensorType) { + case InputDeviceSensorType::ACCELEROMETER: + values[i] *= GRAVITY_MS2_UNIT; + break; + case InputDeviceSensorType::GYROSCOPE: + values[i] *= DEGREE_RADIAN_UNIT; + break; + default: + break; + } + } +} + +SensorInputMapper::SensorInputMapper(InputDeviceContext& deviceContext) + : InputMapper(deviceContext) {} + +SensorInputMapper::~SensorInputMapper() {} + +uint32_t SensorInputMapper::getSources() { + return AINPUT_SOURCE_SENSOR; +} + +template <typename T> +bool SensorInputMapper::tryGetProperty(std::string keyName, T& outValue) { + const auto& config = getDeviceContext().getConfiguration(); + return config.tryGetProperty(String8(keyName.c_str()), outValue); +} + +void SensorInputMapper::parseSensorConfiguration(InputDeviceSensorType sensorType, int32_t absCode, + int32_t sensorDataIndex, const Axis& axis) { + auto it = mSensors.find(sensorType); + if (it == mSensors.end()) { + Sensor sensor = createSensor(sensorType, axis); + sensor.dataVec[sensorDataIndex] = absCode; + mSensors.emplace(sensorType, sensor); + } else { + it->second.dataVec[sensorDataIndex] = absCode; + } +} + +void SensorInputMapper::populateDeviceInfo(InputDeviceInfo* info) { + InputMapper::populateDeviceInfo(info); + + for (const auto& [sensorType, sensor] : mSensors) { + info->addSensorInfo(sensor.sensorInfo); + info->setHasSensor(true); + } +} + +void SensorInputMapper::dump(std::string& dump) { + dump += INDENT2 "Sensor Input Mapper:\n"; + dump += StringPrintf(INDENT3 " isDeviceEnabled %d\n", getDeviceContext().isDeviceEnabled()); + dump += StringPrintf(INDENT3 " mHasHardwareTimestamp %d\n", mHasHardwareTimestamp); + dump += INDENT3 "Sensors:\n"; + for (const auto& [sensorType, sensor] : mSensors) { + dump += StringPrintf(INDENT4 "%s\n", NamedEnum::string(sensorType).c_str()); + dump += StringPrintf(INDENT5 "enabled: %d\n", sensor.enabled); + dump += StringPrintf(INDENT5 "samplingPeriod: %lld\n", sensor.samplingPeriod.count()); + dump += StringPrintf(INDENT5 "maxBatchReportLatency: %lld\n", + sensor.maxBatchReportLatency.count()); + dump += StringPrintf(INDENT5 "maxRange: %f\n", sensor.sensorInfo.maxRange); + dump += StringPrintf(INDENT5 "power: %f\n", sensor.sensorInfo.power); + for (ssize_t i = 0; i < SENSOR_VEC_LEN; i++) { + int32_t rawAxis = sensor.dataVec[i]; + dump += StringPrintf(INDENT5 "[%zd]: rawAxis: %d \n", i, rawAxis); + const auto it = mAxes.find(rawAxis); + if (it != mAxes.end()) { + const Axis& axis = it->second; + dump += StringPrintf(INDENT5 " min=%0.5f, max=%0.5f, flat=%0.5f, fuzz=%0.5f," + "resolution=%0.5f\n", + axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution); + dump += StringPrintf(INDENT5 " scale=%0.5f, offset=%0.5f\n", axis.scale, + axis.offset); + dump += StringPrintf(INDENT5 " rawMin=%d, rawMax=%d, " + "rawFlat=%d, rawFuzz=%d, rawResolution=%d\n", + axis.rawAxisInfo.minValue, axis.rawAxisInfo.maxValue, + axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz, + axis.rawAxisInfo.resolution); + } + } + } +} + +void SensorInputMapper::configure(nsecs_t when, const InputReaderConfiguration* config, + uint32_t changes) { + InputMapper::configure(when, config, changes); + + if (!changes) { // first time only + mDeviceEnabled = true; + // Check if device has MSC_TIMESTAMP event. + mHasHardwareTimestamp = getDeviceContext().hasMscEvent(MSC_TIMESTAMP); + // Collect all axes. + for (int32_t abs = ABS_X; abs <= ABS_MAX; abs++) { + // axis must be claimed by sensor class device + if (!(getAbsAxisUsage(abs, getDeviceContext().getDeviceClasses()) + .test(InputDeviceClass::SENSOR))) { + continue; + } + RawAbsoluteAxisInfo rawAxisInfo; + getAbsoluteAxisInfo(abs, &rawAxisInfo); + if (rawAxisInfo.valid) { + AxisInfo axisInfo; + // Axis doesn't need to be mapped, as sensor mapper doesn't generate any motion + // input events + axisInfo.mode = AxisInfo::MODE_NORMAL; + axisInfo.axis = -1; + // Check key layout map for sensor data mapping to axes + auto ret = getDeviceContext().mapSensor(abs); + if (ret) { + InputDeviceSensorType sensorType = (*ret).first; + int32_t sensorDataIndex = (*ret).second; + const Axis& axis = createAxis(axisInfo, rawAxisInfo); + parseSensorConfiguration(sensorType, abs, sensorDataIndex, axis); + + mAxes.insert({abs, axis}); + } + } + } + } +} + +SensorInputMapper::Axis SensorInputMapper::createAxis(const AxisInfo& axisInfo, + const RawAbsoluteAxisInfo& rawAxisInfo) { + // Apply flat override. + int32_t rawFlat = axisInfo.flatOverride < 0 ? rawAxisInfo.flat : axisInfo.flatOverride; + + float scale = std::numeric_limits<float>::signaling_NaN(); + float offset = 0; + + // resolution is 1 of sensor's unit. For accelerometer, it is G, for gyroscope, + // it is degree/s. + scale = 1.0f / rawAxisInfo.resolution; + offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale; + + const float max = rawAxisInfo.maxValue / rawAxisInfo.resolution; + const float min = rawAxisInfo.minValue / rawAxisInfo.resolution; + const float flat = rawFlat * scale; + const float fuzz = rawAxisInfo.fuzz * scale; + const float resolution = rawAxisInfo.resolution; + + // To eliminate noise while the Sensor is at rest, filter out small variations + // in axis values up front. + const float filter = fuzz ? fuzz : flat * 0.25f; + return Axis(rawAxisInfo, axisInfo, scale, offset, min, max, flat, fuzz, resolution, filter); +} + +void SensorInputMapper::reset(nsecs_t when) { + // Recenter all axes. + for (std::pair<const int32_t, Axis>& pair : mAxes) { + Axis& axis = pair.second; + axis.resetValue(); + } + mHardwareTimestamp = 0; + mPrevMscTime = 0; + InputMapper::reset(when); +} + +SensorInputMapper::Sensor SensorInputMapper::createSensor(InputDeviceSensorType sensorType, + const Axis& axis) { + InputDeviceIdentifier identifier = getDeviceContext().getDeviceIdentifier(); + // Sensor Id will be assigned to device Id to distinguish same sensor from multiple input + // devices, in such a way that the sensor Id will be same as input device Id. + // The sensorType is to distinguish different sensors within one device. + // One input device can only have 1 sensor for each sensor Type. + InputDeviceSensorInfo sensorInfo(identifier.name, std::to_string(identifier.vendor), + identifier.version, sensorType, + InputDeviceSensorAccuracy::ACCURACY_HIGH, + axis.max /* maxRange */, axis.scale /* resolution */, + 0.0f /* power */, 0 /* minDelay */, + 0 /* fifoReservedEventCount */, 0 /* fifoMaxEventCount */, + NamedEnum::string(sensorType), 0 /* maxDelay */, 0 /* flags */, + getDeviceId()); + + std::string prefix = "sensor." + NamedEnum::string(sensorType); + transform(prefix.begin(), prefix.end(), prefix.begin(), ::tolower); + + int32_t reportingMode = 0; + if (!tryGetProperty(prefix + ".reportingMode", reportingMode)) { + sensorInfo.flags |= (reportingMode & REPORTING_MODE_MASK) << REPORTING_MODE_SHIFT; + } + + tryGetProperty(prefix + ".maxDelay", sensorInfo.maxDelay); + + tryGetProperty(prefix + ".minDelay", sensorInfo.minDelay); + + tryGetProperty(prefix + ".power", sensorInfo.power); + + tryGetProperty(prefix + ".fifoReservedEventCount", sensorInfo.fifoReservedEventCount); + + tryGetProperty(prefix + ".fifoMaxEventCount", sensorInfo.fifoMaxEventCount); + + return Sensor(sensorInfo); +} + +void SensorInputMapper::processHardWareTimestamp(nsecs_t evTime, int32_t mscTime) { + // Since MSC_TIMESTAMP initial state is different from the system time, we + // calculate the difference between two MSC_TIMESTAMP events, and use that + // to calculate the system time that should be tagged on the event. + // if the first time MSC_TIMESTAMP, store it + // else calculate difference between previous and current MSC_TIMESTAMP + if (mPrevMscTime == 0) { + mHardwareTimestamp = evTime; + if (DEBUG_SENSOR_EVENT_DETAILS) { + ALOGD("Initialize hardware timestamp = %" PRId64, mHardwareTimestamp); + } + } else { + // Calculate the difference between current msc_timestamp and + // previous msc_timestamp, including when msc_timestamp wraps around. + uint32_t timeDiff = (mPrevMscTime > static_cast<uint32_t>(mscTime)) + ? (UINT32_MAX - mPrevMscTime + static_cast<uint32_t>(mscTime + 1)) + : (static_cast<uint32_t>(mscTime) - mPrevMscTime); + + mHardwareTimestamp += timeDiff * 1000LL; + } + mPrevMscTime = static_cast<uint32_t>(mscTime); +} + +void SensorInputMapper::process(const RawEvent* rawEvent) { + switch (rawEvent->type) { + case EV_ABS: { + auto it = mAxes.find(rawEvent->code); + if (it != mAxes.end()) { + Axis& axis = it->second; + axis.newValue = rawEvent->value * axis.scale + axis.offset; + } + break; + } + + case EV_SYN: + switch (rawEvent->code) { + case SYN_REPORT: + for (std::pair<const int32_t, Axis>& pair : mAxes) { + Axis& axis = pair.second; + axis.currentValue = axis.newValue; + } + sync(rawEvent->when, false /*force*/); + break; + } + break; + + case EV_MSC: + switch (rawEvent->code) { + case MSC_TIMESTAMP: + // hardware timestamp is nano seconds + processHardWareTimestamp(rawEvent->when, rawEvent->value); + break; + } + } +} + +bool SensorInputMapper::setSensorEnabled(InputDeviceSensorType sensorType, bool enabled) { + auto it = mSensors.find(sensorType); + if (it == mSensors.end()) { + return false; + } + + it->second.enabled = enabled; + if (!enabled) { + it->second.resetValue(); + } + + /* Currently we can't enable/disable sensors individually. Enabling any sensor will enable + * the device + */ + mDeviceEnabled = false; + for (const auto& [sensorType, sensor] : mSensors) { + // If any sensor is on we will turn on the device. + if (sensor.enabled) { + mDeviceEnabled = true; + break; + } + } + return true; +} + +void SensorInputMapper::flushSensor(InputDeviceSensorType sensorType) { + auto it = mSensors.find(sensorType); + if (it == mSensors.end()) { + return; + } + auto& sensor = it->second; + sensor.lastSampleTimeNs = 0; + for (size_t i = 0; i < SENSOR_VEC_LEN; i++) { + int32_t abs = sensor.dataVec[i]; + auto itAxis = mAxes.find(abs); + if (itAxis != mAxes.end()) { + Axis& axis = itAxis->second; + axis.resetValue(); + } + } +} + +bool SensorInputMapper::enableSensor(InputDeviceSensorType sensorType, + std::chrono::microseconds samplingPeriod, + std::chrono::microseconds maxBatchReportLatency) { + if (DEBUG_SENSOR_EVENT_DETAILS) { + ALOGD("Enable Sensor %s samplingPeriod %lld maxBatchReportLatency %lld", + NamedEnum::string(sensorType).c_str(), samplingPeriod.count(), + maxBatchReportLatency.count()); + } + + if (!setSensorEnabled(sensorType, true /* enabled */)) { + return false; + } + + // Enable device + if (mDeviceEnabled) { + getDeviceContext().enableDevice(); + } + + // We know the sensor exists now, update the sampling period and batch report latency. + auto it = mSensors.find(sensorType); + it->second.samplingPeriod = + std::chrono::duration_cast<std::chrono::nanoseconds>(samplingPeriod); + it->second.maxBatchReportLatency = + std::chrono::duration_cast<std::chrono::nanoseconds>(maxBatchReportLatency); + return true; +} + +void SensorInputMapper::disableSensor(InputDeviceSensorType sensorType) { + if (DEBUG_SENSOR_EVENT_DETAILS) { + ALOGD("Disable Sensor %s", NamedEnum::string(sensorType).c_str()); + } + + if (!setSensorEnabled(sensorType, false /* enabled */)) { + return; + } + + // Disable device + if (!mDeviceEnabled) { + mHardwareTimestamp = 0; + mPrevMscTime = 0; + getDeviceContext().disableDevice(); + } +} + +void SensorInputMapper::sync(nsecs_t when, bool force) { + for (auto& [sensorType, sensor] : mSensors) { + // Skip if sensor not enabled + if (!sensor.enabled) { + continue; + } + std::vector<float> values; + for (ssize_t i = 0; i < SENSOR_VEC_LEN; i++) { + int32_t abs = sensor.dataVec[i]; + auto it = mAxes.find(abs); + if (it != mAxes.end()) { + const Axis& axis = it->second; + values.push_back(axis.currentValue); + } + } + + nsecs_t timestamp = mHasHardwareTimestamp ? mHardwareTimestamp : when; + if (DEBUG_SENSOR_EVENT_DETAILS) { + ALOGD("Sensor %s timestamp %" PRIu64 " values [%f %f %f]", + NamedEnum::string(sensorType).c_str(), timestamp, values[0], values[1], + values[2]); + } + if (sensor.lastSampleTimeNs.has_value() && + timestamp - sensor.lastSampleTimeNs.value() < sensor.samplingPeriod.count()) { + if (DEBUG_SENSOR_EVENT_DETAILS) { + ALOGD("Sensor %s Skip a sample.", NamedEnum::string(sensorType).c_str()); + } + } else { + // Convert to Android unit + convertFromLinuxToAndroid(values, sensorType); + // Notify dispatcher for sensor event + NotifySensorArgs args(getContext()->getNextId(), when, getDeviceId(), + AINPUT_SOURCE_SENSOR, sensorType, sensor.sensorInfo.accuracy, + sensor.accuracy != + sensor.sensorInfo.accuracy /* accuracyChanged */, + timestamp /* hwTimestamp */, values); + + getListener()->notifySensor(&args); + sensor.lastSampleTimeNs = timestamp; + sensor.accuracy = sensor.sensorInfo.accuracy; + } + } +} + +} // namespace android diff --git a/services/inputflinger/reader/mapper/SensorInputMapper.h b/services/inputflinger/reader/mapper/SensorInputMapper.h new file mode 100644 index 0000000000..337100216e --- /dev/null +++ b/services/inputflinger/reader/mapper/SensorInputMapper.h @@ -0,0 +1,138 @@ +/* + * 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 _UI_INPUTREADER_SENSOR_INPUT_MAPPER_H +#define _UI_INPUTREADER_SENSOR_INPUT_MAPPER_H + +#include "InputMapper.h" + +namespace android { +// sensor data vector length +static constexpr ssize_t SENSOR_VEC_LEN = 3; + +class SensorInputMapper : public InputMapper { +public: + explicit SensorInputMapper(InputDeviceContext& deviceContext); + ~SensorInputMapper() override; + + uint32_t getSources() override; + void populateDeviceInfo(InputDeviceInfo* deviceInfo) override; + void dump(std::string& dump) override; + void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes) override; + void reset(nsecs_t when) override; + void process(const RawEvent* rawEvent) override; + bool enableSensor(InputDeviceSensorType sensorType, std::chrono::microseconds samplingPeriod, + std::chrono::microseconds maxBatchReportLatency) override; + void disableSensor(InputDeviceSensorType sensorType) override; + void flushSensor(InputDeviceSensorType sensorType) override; + +private: + struct Axis { + explicit Axis(const RawAbsoluteAxisInfo& rawAxisInfo, const AxisInfo& axisInfo, float scale, + float offset, float min, float max, float flat, float fuzz, float resolution, + float filter) + : rawAxisInfo(rawAxisInfo), + axisInfo(axisInfo), + scale(scale), + offset(offset), + min(min), + max(max), + flat(flat), + fuzz(fuzz), + resolution(resolution), + filter(filter) { + resetValue(); + } + + RawAbsoluteAxisInfo rawAxisInfo; + AxisInfo axisInfo; + + float scale; // scale factor from raw to normalized values + float offset; // offset to add after scaling for normalization + + float min; // normalized inclusive minimum + float max; // normalized inclusive maximum + float flat; // normalized flat region size + float fuzz; // normalized error tolerance + float resolution; // normalized resolution in units + + float filter; // filter out small variations of this size + float currentValue; // current value + float newValue; // most recent value + + void resetValue() { + this->currentValue = 0; + this->newValue = 0; + } + }; + + struct Sensor { + explicit Sensor(const InputDeviceSensorInfo& sensorInfo) : sensorInfo(sensorInfo) { + resetValue(); + } + bool enabled; + InputDeviceSensorAccuracy accuracy; + std::chrono::nanoseconds samplingPeriod; + std::chrono::nanoseconds maxBatchReportLatency; + // last sample time in nano seconds + std::optional<nsecs_t> lastSampleTimeNs; + InputDeviceSensorInfo sensorInfo; + // Sensor X, Y, Z data mapping to abs + std::array<int32_t, SENSOR_VEC_LEN> dataVec; + void resetValue() { + this->enabled = false; + this->accuracy = InputDeviceSensorAccuracy::ACCURACY_NONE; + this->samplingPeriod = std::chrono::nanoseconds(0); + this->maxBatchReportLatency = std::chrono::nanoseconds(0); + this->lastSampleTimeNs = std::nullopt; + this->dataVec.fill(0); + } + }; + + static Axis createAxis(const AxisInfo& AxisInfo, const RawAbsoluteAxisInfo& rawAxisInfo); + + // Axes indexed by raw ABS_* axis index. + std::unordered_map<int32_t, Axis> mAxes; + + // hardware timestamp from MSC_TIMESTAMP + nsecs_t mHardwareTimestamp; + uint32_t mPrevMscTime; + + bool mDeviceEnabled; + // Does device support MSC_TIMESTAMP + bool mHasHardwareTimestamp; + + // Sensor list + std::unordered_map<InputDeviceSensorType, Sensor> mSensors; + + void sync(nsecs_t when, bool force); + + template <typename T> + bool tryGetProperty(std::string keyName, T& outValue); + + void parseSensorConfiguration(InputDeviceSensorType sensorType, int32_t absCode, + int32_t sensorDataIndex, const Axis& axis); + + void processHardWareTimestamp(nsecs_t evTime, int32_t evValue); + + Sensor createSensor(InputDeviceSensorType sensorType, const Axis& axis); + + bool setSensorEnabled(InputDeviceSensorType sensorType, bool enabled); +}; + +} // namespace android + +#endif // _UI_INPUTREADER_SENSOR_INPUT_MAPPER_H
\ No newline at end of file diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index 76328148c2..c819091ae0 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -284,6 +284,12 @@ private: void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {} void notifyUntrustedTouch(const std::string& obscuringPackage) override {} + void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType, + InputDeviceSensorAccuracy accuracy, nsecs_t timestamp, + const std::vector<float>& values) override {} + + void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType, + InputDeviceSensorAccuracy accuracy) override {} void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override { *outConfig = mConfig; diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp index c26a389342..23f30260bc 100644 --- a/services/inputflinger/tests/InputReader_test.cpp +++ b/services/inputflinger/tests/InputReader_test.cpp @@ -22,6 +22,7 @@ #include <InputReaderFactory.h> #include <KeyboardInputMapper.h> #include <MultiTouchInputMapper.h> +#include <SensorInputMapper.h> #include <SingleTouchInputMapper.h> #include <SwitchInputMapper.h> #include <TestInputListener.h> @@ -364,6 +365,11 @@ class FakeEventHub : public EventHubInterface { uint32_t flags; }; + struct SensorInfo { + InputDeviceSensorType sensorType; + int32_t sensorDataIndex; + }; + struct Device { InputDeviceIdentifier identifier; Flags<InputDeviceClass> classes; @@ -377,6 +383,8 @@ class FakeEventHub : public EventHubInterface { KeyedVector<int32_t, KeyInfo> keysByScanCode; KeyedVector<int32_t, KeyInfo> keysByUsageCode; KeyedVector<int32_t, bool> leds; + std::unordered_map<int32_t, SensorInfo> sensorsByAbsCode; + BitArray<MSC_MAX> mscBitmask; std::vector<VirtualKeyDefinition> virtualKeys; bool enabled; @@ -535,6 +543,22 @@ public: device->leds.add(led, initialState); } + void addSensorAxis(int32_t deviceId, int32_t absCode, InputDeviceSensorType sensorType, + int32_t sensorDataIndex) { + Device* device = getDevice(deviceId); + SensorInfo info; + info.sensorType = sensorType; + info.sensorDataIndex = sensorDataIndex; + device->sensorsByAbsCode.emplace(absCode, info); + } + + void setMscEvent(int32_t deviceId, int32_t mscEvent) { + Device* device = getDevice(deviceId); + typename BitArray<MSC_MAX>::Buffer buffer; + buffer[mscEvent / 32] = 1 << mscEvent % 32; + device->mscBitmask.loadFromBuffer(buffer); + } + bool getLedState(int32_t deviceId, int32_t led) { Device* device = getDevice(deviceId); return device->leds.valueFor(led); @@ -630,6 +654,14 @@ private: bool hasInputProperty(int32_t, int) const override { return false; } + bool hasMscEvent(int32_t deviceId, int mscEvent) const override final { + Device* device = getDevice(deviceId); + if (device) { + return mscEvent >= 0 && mscEvent <= MSC_MAX ? device->mscBitmask.test(mscEvent) : false; + } + return false; + } + status_t mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, int32_t metaState, int32_t* outKeycode, int32_t* outMetaState, uint32_t* outFlags) const override { Device* device = getDevice(deviceId); @@ -669,6 +701,20 @@ private: status_t mapAxis(int32_t, int32_t, AxisInfo*) const override { return NAME_NOT_FOUND; } + base::Result<std::pair<InputDeviceSensorType, int32_t>> mapSensor(int32_t deviceId, + int32_t absCode) { + Device* device = getDevice(deviceId); + if (!device) { + return Errorf("Sensor device not found."); + } + auto it = device->sensorsByAbsCode.find(absCode); + if (it == device->sensorsByAbsCode.end()) { + return Errorf("Sensor map not found."); + } + const SensorInfo& info = it->second; + return std::make_pair(info.sensorType, info.sensorDataIndex); + } + void setExcludedDevices(const std::vector<std::string>& devices) override { mExcludedDevices = devices; } @@ -2574,6 +2620,157 @@ TEST_F(VibratorInputMapperTest, Vibrate) { ASSERT_TRUE(mapper.isVibrating()); } +// --- SensorInputMapperTest --- + +class SensorInputMapperTest : public InputMapperTest { +protected: + static const int32_t ACCEL_RAW_MIN; + static const int32_t ACCEL_RAW_MAX; + static const int32_t ACCEL_RAW_FUZZ; + static const int32_t ACCEL_RAW_FLAT; + static const int32_t ACCEL_RAW_RESOLUTION; + + static const int32_t GYRO_RAW_MIN; + static const int32_t GYRO_RAW_MAX; + static const int32_t GYRO_RAW_FUZZ; + static const int32_t GYRO_RAW_FLAT; + static const int32_t GYRO_RAW_RESOLUTION; + + static const float GRAVITY_MS2_UNIT; + static const float DEGREE_RADIAN_UNIT; + + void prepareAccelAxes(); + void prepareGyroAxes(); + void setAccelProperties(); + void setGyroProperties(); + void SetUp() override { InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::SENSOR); } +}; + +const int32_t SensorInputMapperTest::ACCEL_RAW_MIN = -32768; +const int32_t SensorInputMapperTest::ACCEL_RAW_MAX = 32768; +const int32_t SensorInputMapperTest::ACCEL_RAW_FUZZ = 16; +const int32_t SensorInputMapperTest::ACCEL_RAW_FLAT = 0; +const int32_t SensorInputMapperTest::ACCEL_RAW_RESOLUTION = 8192; + +const int32_t SensorInputMapperTest::GYRO_RAW_MIN = -2097152; +const int32_t SensorInputMapperTest::GYRO_RAW_MAX = 2097152; +const int32_t SensorInputMapperTest::GYRO_RAW_FUZZ = 16; +const int32_t SensorInputMapperTest::GYRO_RAW_FLAT = 0; +const int32_t SensorInputMapperTest::GYRO_RAW_RESOLUTION = 1024; + +const float SensorInputMapperTest::GRAVITY_MS2_UNIT = 9.80665f; +const float SensorInputMapperTest::DEGREE_RADIAN_UNIT = 0.0174533f; + +void SensorInputMapperTest::prepareAccelAxes() { + mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_FUZZ, + ACCEL_RAW_FLAT, ACCEL_RAW_RESOLUTION); + mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_FUZZ, + ACCEL_RAW_FLAT, ACCEL_RAW_RESOLUTION); + mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Z, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_FUZZ, + ACCEL_RAW_FLAT, ACCEL_RAW_RESOLUTION); +} + +void SensorInputMapperTest::prepareGyroAxes() { + mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_RX, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_FUZZ, + GYRO_RAW_FLAT, GYRO_RAW_RESOLUTION); + mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_RY, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_FUZZ, + GYRO_RAW_FLAT, GYRO_RAW_RESOLUTION); + mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_RZ, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_FUZZ, + GYRO_RAW_FLAT, GYRO_RAW_RESOLUTION); +} + +void SensorInputMapperTest::setAccelProperties() { + mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 0, InputDeviceSensorType::ACCELEROMETER, + /* sensorDataIndex */ 0); + mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 1, InputDeviceSensorType::ACCELEROMETER, + /* sensorDataIndex */ 1); + mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 2, InputDeviceSensorType::ACCELEROMETER, + /* sensorDataIndex */ 2); + mFakeEventHub->setMscEvent(EVENTHUB_ID, MSC_TIMESTAMP); + addConfigurationProperty("sensor.accelerometer.reportingMode", "0"); + addConfigurationProperty("sensor.accelerometer.maxDelay", "100000"); + addConfigurationProperty("sensor.accelerometer.minDelay", "5000"); + addConfigurationProperty("sensor.accelerometer.power", "1.5"); +} + +void SensorInputMapperTest::setGyroProperties() { + mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 3, InputDeviceSensorType::GYROSCOPE, + /* sensorDataIndex */ 0); + mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 4, InputDeviceSensorType::GYROSCOPE, + /* sensorDataIndex */ 1); + mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 5, InputDeviceSensorType::GYROSCOPE, + /* sensorDataIndex */ 2); + mFakeEventHub->setMscEvent(EVENTHUB_ID, MSC_TIMESTAMP); + addConfigurationProperty("sensor.gyroscope.reportingMode", "0"); + addConfigurationProperty("sensor.gyroscope.maxDelay", "100000"); + addConfigurationProperty("sensor.gyroscope.minDelay", "5000"); + addConfigurationProperty("sensor.gyroscope.power", "0.8"); +} + +TEST_F(SensorInputMapperTest, GetSources) { + SensorInputMapper& mapper = addMapperAndConfigure<SensorInputMapper>(); + + ASSERT_EQ(static_cast<uint32_t>(AINPUT_SOURCE_SENSOR), mapper.getSources()); +} + +TEST_F(SensorInputMapperTest, ProcessAccelerometerSensor) { + setAccelProperties(); + prepareAccelAxes(); + SensorInputMapper& mapper = addMapperAndConfigure<SensorInputMapper>(); + + ASSERT_TRUE(mapper.enableSensor(InputDeviceSensorType::ACCELEROMETER, + std::chrono::microseconds(10000), + std::chrono::microseconds(0))); + process(mapper, ARBITRARY_TIME, EV_ABS, ABS_X, 20000); + process(mapper, ARBITRARY_TIME, EV_ABS, ABS_Y, -20000); + process(mapper, ARBITRARY_TIME, EV_ABS, ABS_Z, 40000); + process(mapper, ARBITRARY_TIME, EV_MSC, MSC_TIMESTAMP, 1000); + process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + + NotifySensorArgs args; + std::vector<float> values = {20000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT, + -20000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT, + 40000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT}; + + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifySensorWasCalled(&args)); + ASSERT_EQ(args.source, AINPUT_SOURCE_SENSOR); + ASSERT_EQ(args.deviceId, DEVICE_ID); + ASSERT_EQ(args.sensorType, InputDeviceSensorType::ACCELEROMETER); + ASSERT_EQ(args.accuracy, InputDeviceSensorAccuracy::ACCURACY_HIGH); + ASSERT_EQ(args.hwTimestamp, ARBITRARY_TIME); + ASSERT_EQ(args.values, values); + mapper.flushSensor(InputDeviceSensorType::ACCELEROMETER); +} + +TEST_F(SensorInputMapperTest, ProcessGyroscopeSensor) { + setGyroProperties(); + prepareGyroAxes(); + SensorInputMapper& mapper = addMapperAndConfigure<SensorInputMapper>(); + + ASSERT_TRUE(mapper.enableSensor(InputDeviceSensorType::GYROSCOPE, + std::chrono::microseconds(10000), + std::chrono::microseconds(0))); + process(mapper, ARBITRARY_TIME, EV_ABS, ABS_RX, 20000); + process(mapper, ARBITRARY_TIME, EV_ABS, ABS_RY, -20000); + process(mapper, ARBITRARY_TIME, EV_ABS, ABS_RZ, 40000); + process(mapper, ARBITRARY_TIME, EV_MSC, MSC_TIMESTAMP, 1000); + process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + + NotifySensorArgs args; + std::vector<float> values = {20000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT, + -20000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT, + 40000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT}; + + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifySensorWasCalled(&args)); + ASSERT_EQ(args.source, AINPUT_SOURCE_SENSOR); + ASSERT_EQ(args.deviceId, DEVICE_ID); + ASSERT_EQ(args.sensorType, InputDeviceSensorType::GYROSCOPE); + ASSERT_EQ(args.accuracy, InputDeviceSensorAccuracy::ACCURACY_HIGH); + ASSERT_EQ(args.hwTimestamp, ARBITRARY_TIME); + ASSERT_EQ(args.values, values); + mapper.flushSensor(InputDeviceSensorType::GYROSCOPE); +} + // --- KeyboardInputMapperTest --- class KeyboardInputMapperTest : public InputMapperTest { diff --git a/services/inputflinger/tests/TestInputListener.cpp b/services/inputflinger/tests/TestInputListener.cpp index 1050ab8601..295c6e3057 100644 --- a/services/inputflinger/tests/TestInputListener.cpp +++ b/services/inputflinger/tests/TestInputListener.cpp @@ -80,6 +80,12 @@ void TestInputListener::assertNotifySwitchWasCalled(NotifySwitchArgs* outEventAr "Expected notifySwitch() to have been called.")); } +void TestInputListener::assertNotifySensorWasCalled(NotifySensorArgs* outEventArgs) { + ASSERT_NO_FATAL_FAILURE( + assertCalled<NotifySensorArgs>(outEventArgs, + "Expected notifySensor() to have been called.")); +} + void TestInputListener::assertNotifyCaptureWasCalled( NotifyPointerCaptureChangedArgs* outEventArgs) { ASSERT_NO_FATAL_FAILURE( @@ -155,4 +161,8 @@ void TestInputListener::notifyPointerCaptureChanged(const NotifyPointerCaptureCh notify<NotifyPointerCaptureChangedArgs>(args); } +void TestInputListener::notifySensor(const NotifySensorArgs* args) { + notify<NotifySensorArgs>(args); +} + } // namespace android diff --git a/services/inputflinger/tests/TestInputListener.h b/services/inputflinger/tests/TestInputListener.h index 887d4eadb1..e54350a4c8 100644 --- a/services/inputflinger/tests/TestInputListener.h +++ b/services/inputflinger/tests/TestInputListener.h @@ -55,6 +55,7 @@ public: void assertNotifySwitchWasCalled(NotifySwitchArgs* outEventArgs = nullptr); void assertNotifyCaptureWasCalled(NotifyPointerCaptureChangedArgs* outEventArgs = nullptr); + void assertNotifySensorWasCalled(NotifySensorArgs* outEventArgs = nullptr); private: template <class NotifyArgsType> @@ -76,6 +77,8 @@ private: virtual void notifySwitch(const NotifySwitchArgs* args) override; + virtual void notifySensor(const NotifySensorArgs* args) override; + virtual void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) override; std::mutex mLock; @@ -88,6 +91,7 @@ private: std::vector<NotifyKeyArgs>, // std::vector<NotifyMotionArgs>, // std::vector<NotifySwitchArgs>, // + std::vector<NotifySensorArgs>, // std::vector<NotifyPointerCaptureChangedArgs>> // mQueues GUARDED_BY(mLock); }; |