1 /*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <locale>
18
19 #include <ftl/enum.h>
20
21 #include "../Macros.h"
22 #include "SensorInputMapper.h"
23
24 // Log detailed debug messages about each sensor event notification to the dispatcher.
25 constexpr bool DEBUG_SENSOR_EVENT_DETAILS = false;
26
27 namespace android {
28
29 // Mask for the LSB 2nd, 3rd and fourth bits.
30 constexpr int REPORTING_MODE_MASK = 0xE;
31 constexpr int REPORTING_MODE_SHIFT = 1;
32 constexpr float GRAVITY_MS2_UNIT = 9.80665f;
33 constexpr float DEGREE_RADIAN_UNIT = 0.0174533f;
34
35 /* Convert the sensor data from Linux to Android
36 * Linux accelerometer unit is per g, Android unit is m/s^2
37 * Linux gyroscope unit is degree/second, Android unit is radians/second
38 */
convertFromLinuxToAndroid(std::vector<float> & values,InputDeviceSensorType sensorType)39 static void convertFromLinuxToAndroid(std::vector<float>& values,
40 InputDeviceSensorType sensorType) {
41 for (size_t i = 0; i < values.size(); i++) {
42 switch (sensorType) {
43 case InputDeviceSensorType::ACCELEROMETER:
44 values[i] *= GRAVITY_MS2_UNIT;
45 break;
46 case InputDeviceSensorType::GYROSCOPE:
47 values[i] *= DEGREE_RADIAN_UNIT;
48 break;
49 default:
50 break;
51 }
52 }
53 }
54
SensorInputMapper(InputDeviceContext & deviceContext,const InputReaderConfiguration & readerConfig)55 SensorInputMapper::SensorInputMapper(InputDeviceContext& deviceContext,
56 const InputReaderConfiguration& readerConfig)
57 : InputMapper(deviceContext, readerConfig) {}
58
~SensorInputMapper()59 SensorInputMapper::~SensorInputMapper() {}
60
getSources() const61 uint32_t SensorInputMapper::getSources() const {
62 return AINPUT_SOURCE_SENSOR;
63 }
64
parseSensorConfiguration(InputDeviceSensorType sensorType,int32_t absCode,int32_t sensorDataIndex,const Axis & axis)65 void SensorInputMapper::parseSensorConfiguration(InputDeviceSensorType sensorType, int32_t absCode,
66 int32_t sensorDataIndex, const Axis& axis) {
67 auto it = mSensors.find(sensorType);
68 if (it == mSensors.end()) {
69 Sensor sensor = createSensor(sensorType, axis);
70 sensor.dataVec[sensorDataIndex] = absCode;
71 mSensors.emplace(sensorType, sensor);
72 } else {
73 it->second.dataVec[sensorDataIndex] = absCode;
74 }
75 }
76
populateDeviceInfo(InputDeviceInfo & info)77 void SensorInputMapper::populateDeviceInfo(InputDeviceInfo& info) {
78 InputMapper::populateDeviceInfo(info);
79
80 for (const auto& [sensorType, sensor] : mSensors) {
81 info.addSensorInfo(sensor.sensorInfo);
82 info.setHasSensor(true);
83 }
84 }
85
dump(std::string & dump)86 void SensorInputMapper::dump(std::string& dump) {
87 dump += INDENT2 "Sensor Input Mapper:\n";
88 dump += StringPrintf(INDENT3 " isDeviceEnabled %d\n", getDeviceContext().isDeviceEnabled());
89 dump += StringPrintf(INDENT3 " mHasHardwareTimestamp %d\n", mHasHardwareTimestamp);
90 dump += INDENT3 "Sensors:\n";
91 for (const auto& [sensorType, sensor] : mSensors) {
92 dump += StringPrintf(INDENT4 "%s\n", ftl::enum_string(sensorType).c_str());
93 dump += StringPrintf(INDENT5 "enabled: %d\n", sensor.enabled);
94 dump += StringPrintf(INDENT5 "samplingPeriod: %lld\n", sensor.samplingPeriod.count());
95 dump += StringPrintf(INDENT5 "maxBatchReportLatency: %lld\n",
96 sensor.maxBatchReportLatency.count());
97 dump += StringPrintf(INDENT5 "maxRange: %f\n", sensor.sensorInfo.maxRange);
98 dump += StringPrintf(INDENT5 "power: %f\n", sensor.sensorInfo.power);
99 for (ssize_t i = 0; i < SENSOR_VEC_LEN; i++) {
100 int32_t rawAxis = sensor.dataVec[i];
101 dump += StringPrintf(INDENT5 "[%zd]: rawAxis: %d \n", i, rawAxis);
102 const auto it = mAxes.find(rawAxis);
103 if (it != mAxes.end()) {
104 const Axis& axis = it->second;
105 dump += StringPrintf(INDENT5 " min=%0.5f, max=%0.5f, flat=%0.5f, fuzz=%0.5f,"
106 "resolution=%0.5f\n",
107 axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution);
108 dump += StringPrintf(INDENT5 " scale=%0.5f, offset=%0.5f\n", axis.scale,
109 axis.offset);
110 dump += StringPrintf(INDENT5 " rawMin=%d, rawMax=%d, "
111 "rawFlat=%d, rawFuzz=%d, rawResolution=%d\n",
112 axis.rawAxisInfo.minValue, axis.rawAxisInfo.maxValue,
113 axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz,
114 axis.rawAxisInfo.resolution);
115 }
116 }
117 }
118 }
119
reconfigure(nsecs_t when,const InputReaderConfiguration & config,ConfigurationChanges changes)120 std::list<NotifyArgs> SensorInputMapper::reconfigure(nsecs_t when,
121 const InputReaderConfiguration& config,
122 ConfigurationChanges changes) {
123 std::list<NotifyArgs> out = InputMapper::reconfigure(when, config, changes);
124
125 if (!changes.any()) { // first time only
126 mDeviceEnabled = true;
127 // Check if device has MSC_TIMESTAMP event.
128 mHasHardwareTimestamp = getDeviceContext().hasMscEvent(MSC_TIMESTAMP);
129 // Collect all axes.
130 for (int32_t abs = ABS_X; abs <= ABS_MAX; abs++) {
131 // axis must be claimed by sensor class device
132 if (!(getAbsAxisUsage(abs, getDeviceContext().getDeviceClasses())
133 .test(InputDeviceClass::SENSOR))) {
134 continue;
135 }
136 if (std::optional<RawAbsoluteAxisInfo> rawAxisInfo = getAbsoluteAxisInfo(abs);
137 rawAxisInfo) {
138 AxisInfo axisInfo;
139 // Axis doesn't need to be mapped, as sensor mapper doesn't generate any motion
140 // input events
141 axisInfo.mode = AxisInfo::MODE_NORMAL;
142 axisInfo.axis = -1;
143 // Check key layout map for sensor data mapping to axes
144 auto ret = getDeviceContext().mapSensor(abs);
145 if (ret.ok()) {
146 InputDeviceSensorType sensorType = (*ret).first;
147 int32_t sensorDataIndex = (*ret).second;
148 const Axis& axis = createAxis(axisInfo, rawAxisInfo.value());
149 parseSensorConfiguration(sensorType, abs, sensorDataIndex, axis);
150
151 mAxes.insert({abs, axis});
152 }
153 }
154 }
155 }
156 return out;
157 }
158
createAxis(const AxisInfo & axisInfo,const RawAbsoluteAxisInfo & rawAxisInfo)159 SensorInputMapper::Axis SensorInputMapper::createAxis(const AxisInfo& axisInfo,
160 const RawAbsoluteAxisInfo& rawAxisInfo) {
161 // Apply flat override.
162 int32_t rawFlat = axisInfo.flatOverride < 0 ? rawAxisInfo.flat : axisInfo.flatOverride;
163
164 float scale = std::numeric_limits<float>::signaling_NaN();
165 float offset = 0;
166
167 // resolution is 1 of sensor's unit. For accelerometer, it is G, for gyroscope,
168 // it is degree/s.
169 scale = 1.0f / rawAxisInfo.resolution;
170 offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale;
171
172 const float max = rawAxisInfo.maxValue / rawAxisInfo.resolution;
173 const float min = rawAxisInfo.minValue / rawAxisInfo.resolution;
174 const float flat = rawFlat * scale;
175 const float fuzz = rawAxisInfo.fuzz * scale;
176 const float resolution = rawAxisInfo.resolution;
177
178 // To eliminate noise while the Sensor is at rest, filter out small variations
179 // in axis values up front.
180 const float filter = fuzz ? fuzz : flat * 0.25f;
181 return Axis(rawAxisInfo, axisInfo, scale, offset, min, max, flat, fuzz, resolution, filter);
182 }
183
reset(nsecs_t when)184 std::list<NotifyArgs> SensorInputMapper::reset(nsecs_t when) {
185 // Recenter all axes.
186 for (std::pair<const int32_t, Axis>& pair : mAxes) {
187 Axis& axis = pair.second;
188 axis.resetValue();
189 }
190 mHardwareTimestamp = 0;
191 mPrevMscTime = 0;
192 return InputMapper::reset(when);
193 }
194
createSensor(InputDeviceSensorType sensorType,const Axis & axis)195 SensorInputMapper::Sensor SensorInputMapper::createSensor(InputDeviceSensorType sensorType,
196 const Axis& axis) {
197 InputDeviceIdentifier identifier = getDeviceContext().getDeviceIdentifier();
198 const auto& config = getDeviceContext().getConfiguration();
199
200 std::string prefix = "sensor." + ftl::enum_string(sensorType);
201 transform(prefix.begin(), prefix.end(), prefix.begin(), ::tolower);
202
203 int32_t flags = 0;
204 std::optional<int32_t> reportingMode = config.getInt(prefix + ".reportingMode");
205 if (reportingMode.has_value()) {
206 flags |= (*reportingMode & REPORTING_MODE_MASK) << REPORTING_MODE_SHIFT;
207 }
208
209 // Sensor Id will be assigned to device Id to distinguish same sensor from multiple input
210 // devices, in such a way that the sensor Id will be same as input device Id.
211 // The sensorType is to distinguish different sensors within one device.
212 // One input device can only have 1 sensor for each sensor Type.
213 InputDeviceSensorInfo sensorInfo(identifier.name, std::to_string(identifier.vendor),
214 identifier.version, sensorType,
215 InputDeviceSensorAccuracy::HIGH,
216 /*maxRange=*/axis.max, /*resolution=*/axis.scale,
217 /*power=*/config.getFloat(prefix + ".power").value_or(0.0f),
218 /*minDelay=*/config.getInt(prefix + ".minDelay").value_or(0),
219 /*fifoReservedEventCount=*/
220 config.getInt(prefix + ".fifoReservedEventCount").value_or(0),
221 /*fifoMaxEventCount=*/
222 config.getInt(prefix + ".fifoMaxEventCount").value_or(0),
223 ftl::enum_string(sensorType),
224 /*maxDelay=*/config.getInt(prefix + ".maxDelay").value_or(0),
225 /*flags=*/flags, getDeviceId());
226
227 return Sensor(sensorInfo);
228 }
229
processHardWareTimestamp(nsecs_t evTime,int32_t mscTime)230 void SensorInputMapper::processHardWareTimestamp(nsecs_t evTime, int32_t mscTime) {
231 // Since MSC_TIMESTAMP initial state is different from the system time, we
232 // calculate the difference between two MSC_TIMESTAMP events, and use that
233 // to calculate the system time that should be tagged on the event.
234 // if the first time MSC_TIMESTAMP, store it
235 // else calculate difference between previous and current MSC_TIMESTAMP
236 if (mPrevMscTime == 0) {
237 mHardwareTimestamp = evTime;
238 if (DEBUG_SENSOR_EVENT_DETAILS) {
239 ALOGD("Initialize hardware timestamp = %" PRId64, mHardwareTimestamp);
240 }
241 } else {
242 // Calculate the difference between current msc_timestamp and
243 // previous msc_timestamp, including when msc_timestamp wraps around.
244 uint32_t timeDiff = (mPrevMscTime > static_cast<uint32_t>(mscTime))
245 ? (UINT32_MAX - mPrevMscTime + static_cast<uint32_t>(mscTime + 1))
246 : (static_cast<uint32_t>(mscTime) - mPrevMscTime);
247
248 mHardwareTimestamp += timeDiff * 1000LL;
249 }
250 mPrevMscTime = static_cast<uint32_t>(mscTime);
251 }
252
process(const RawEvent & rawEvent)253 std::list<NotifyArgs> SensorInputMapper::process(const RawEvent& rawEvent) {
254 std::list<NotifyArgs> out;
255 switch (rawEvent.type) {
256 case EV_ABS: {
257 auto it = mAxes.find(rawEvent.code);
258 if (it != mAxes.end()) {
259 Axis& axis = it->second;
260 axis.newValue = rawEvent.value * axis.scale + axis.offset;
261 }
262 break;
263 }
264
265 case EV_SYN:
266 switch (rawEvent.code) {
267 case SYN_REPORT:
268 for (std::pair<const int32_t, Axis>& pair : mAxes) {
269 Axis& axis = pair.second;
270 axis.currentValue = axis.newValue;
271 }
272 out += sync(rawEvent.when, /*force=*/false);
273 break;
274 }
275 break;
276
277 case EV_MSC:
278 switch (rawEvent.code) {
279 case MSC_TIMESTAMP:
280 // hardware timestamp is nano seconds
281 processHardWareTimestamp(rawEvent.when, rawEvent.value);
282 break;
283 }
284 }
285 return out;
286 }
287
setSensorEnabled(InputDeviceSensorType sensorType,bool enabled)288 bool SensorInputMapper::setSensorEnabled(InputDeviceSensorType sensorType, bool enabled) {
289 auto it = mSensors.find(sensorType);
290 if (it == mSensors.end()) {
291 return false;
292 }
293
294 it->second.enabled = enabled;
295 if (!enabled) {
296 it->second.resetValue();
297 }
298
299 /* Currently we can't enable/disable sensors individually. Enabling any sensor will enable
300 * the device
301 */
302 mDeviceEnabled = false;
303 for (const auto& [_, sensor] : mSensors) {
304 // If any sensor is on we will turn on the device.
305 if (sensor.enabled) {
306 mDeviceEnabled = true;
307 break;
308 }
309 }
310 return true;
311 }
312
flushSensor(InputDeviceSensorType sensorType)313 void SensorInputMapper::flushSensor(InputDeviceSensorType sensorType) {
314 auto it = mSensors.find(sensorType);
315 if (it == mSensors.end()) {
316 return;
317 }
318 auto& sensor = it->second;
319 sensor.lastSampleTimeNs = 0;
320 for (size_t i = 0; i < SENSOR_VEC_LEN; i++) {
321 int32_t abs = sensor.dataVec[i];
322 auto itAxis = mAxes.find(abs);
323 if (itAxis != mAxes.end()) {
324 Axis& axis = itAxis->second;
325 axis.resetValue();
326 }
327 }
328 }
329
enableSensor(InputDeviceSensorType sensorType,std::chrono::microseconds samplingPeriod,std::chrono::microseconds maxBatchReportLatency)330 bool SensorInputMapper::enableSensor(InputDeviceSensorType sensorType,
331 std::chrono::microseconds samplingPeriod,
332 std::chrono::microseconds maxBatchReportLatency) {
333 if (DEBUG_SENSOR_EVENT_DETAILS) {
334 ALOGD("Enable Sensor %s samplingPeriod %lld maxBatchReportLatency %lld",
335 ftl::enum_string(sensorType).c_str(), samplingPeriod.count(),
336 maxBatchReportLatency.count());
337 }
338
339 if (!setSensorEnabled(sensorType, /*enabled=*/true)) {
340 return false;
341 }
342
343 // Enable device
344 if (mDeviceEnabled) {
345 getDeviceContext().enableDevice();
346 }
347
348 // We know the sensor exists now, update the sampling period and batch report latency.
349 auto it = mSensors.find(sensorType);
350 it->second.samplingPeriod =
351 std::chrono::duration_cast<std::chrono::nanoseconds>(samplingPeriod);
352 it->second.maxBatchReportLatency =
353 std::chrono::duration_cast<std::chrono::nanoseconds>(maxBatchReportLatency);
354 return true;
355 }
356
disableSensor(InputDeviceSensorType sensorType)357 void SensorInputMapper::disableSensor(InputDeviceSensorType sensorType) {
358 if (DEBUG_SENSOR_EVENT_DETAILS) {
359 ALOGD("Disable Sensor %s", ftl::enum_string(sensorType).c_str());
360 }
361
362 if (!setSensorEnabled(sensorType, /*enabled=*/false)) {
363 return;
364 }
365
366 // Disable device
367 if (!mDeviceEnabled) {
368 mHardwareTimestamp = 0;
369 mPrevMscTime = 0;
370 getDeviceContext().disableDevice();
371 }
372 }
373
sync(nsecs_t when,bool force)374 std::list<NotifyArgs> SensorInputMapper::sync(nsecs_t when, bool force) {
375 std::list<NotifyArgs> out;
376 for (auto& [sensorType, sensor] : mSensors) {
377 // Skip if sensor not enabled
378 if (!sensor.enabled) {
379 continue;
380 }
381 std::vector<float> values;
382 for (ssize_t i = 0; i < SENSOR_VEC_LEN; i++) {
383 int32_t abs = sensor.dataVec[i];
384 auto it = mAxes.find(abs);
385 if (it != mAxes.end()) {
386 const Axis& axis = it->second;
387 values.push_back(axis.currentValue);
388 }
389 }
390
391 nsecs_t timestamp = mHasHardwareTimestamp ? mHardwareTimestamp : when;
392 if (DEBUG_SENSOR_EVENT_DETAILS) {
393 ALOGD("Sensor %s timestamp %" PRIu64 " values [%f %f %f]",
394 ftl::enum_string(sensorType).c_str(), timestamp, values[0], values[1], values[2]);
395 }
396 if (sensor.lastSampleTimeNs.has_value() &&
397 timestamp - sensor.lastSampleTimeNs.value() < sensor.samplingPeriod.count()) {
398 if (DEBUG_SENSOR_EVENT_DETAILS) {
399 ALOGD("Sensor %s Skip a sample.", ftl::enum_string(sensorType).c_str());
400 }
401 } else {
402 // Convert to Android unit
403 convertFromLinuxToAndroid(values, sensorType);
404 // Notify dispatcher for sensor event
405 out.push_back(NotifySensorArgs(getContext()->getNextId(), when, getDeviceId(),
406 AINPUT_SOURCE_SENSOR, sensorType,
407 sensor.sensorInfo.accuracy,
408 /*accuracyChanged=*/sensor.accuracy !=
409 sensor.sensorInfo.accuracy,
410 /*hwTimestamp=*/timestamp, values));
411 sensor.lastSampleTimeNs = timestamp;
412 sensor.accuracy = sensor.sensorInfo.accuracy;
413 }
414 }
415 return out;
416 }
417
418 } // namespace android
419