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 RawAbsoluteAxisInfo rawAxisInfo;
137 getAbsoluteAxisInfo(abs, &rawAxisInfo);
138 if (rawAxisInfo.valid) {
139 AxisInfo axisInfo;
140 // Axis doesn't need to be mapped, as sensor mapper doesn't generate any motion
141 // input events
142 axisInfo.mode = AxisInfo::MODE_NORMAL;
143 axisInfo.axis = -1;
144 // Check key layout map for sensor data mapping to axes
145 auto ret = getDeviceContext().mapSensor(abs);
146 if (ret.ok()) {
147 InputDeviceSensorType sensorType = (*ret).first;
148 int32_t sensorDataIndex = (*ret).second;
149 const Axis& axis = createAxis(axisInfo, rawAxisInfo);
150 parseSensorConfiguration(sensorType, abs, sensorDataIndex, axis);
151
152 mAxes.insert({abs, axis});
153 }
154 }
155 }
156 }
157 return out;
158 }
159
createAxis(const AxisInfo & axisInfo,const RawAbsoluteAxisInfo & rawAxisInfo)160 SensorInputMapper::Axis SensorInputMapper::createAxis(const AxisInfo& axisInfo,
161 const RawAbsoluteAxisInfo& rawAxisInfo) {
162 // Apply flat override.
163 int32_t rawFlat = axisInfo.flatOverride < 0 ? rawAxisInfo.flat : axisInfo.flatOverride;
164
165 float scale = std::numeric_limits<float>::signaling_NaN();
166 float offset = 0;
167
168 // resolution is 1 of sensor's unit. For accelerometer, it is G, for gyroscope,
169 // it is degree/s.
170 scale = 1.0f / rawAxisInfo.resolution;
171 offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale;
172
173 const float max = rawAxisInfo.maxValue / rawAxisInfo.resolution;
174 const float min = rawAxisInfo.minValue / rawAxisInfo.resolution;
175 const float flat = rawFlat * scale;
176 const float fuzz = rawAxisInfo.fuzz * scale;
177 const float resolution = rawAxisInfo.resolution;
178
179 // To eliminate noise while the Sensor is at rest, filter out small variations
180 // in axis values up front.
181 const float filter = fuzz ? fuzz : flat * 0.25f;
182 return Axis(rawAxisInfo, axisInfo, scale, offset, min, max, flat, fuzz, resolution, filter);
183 }
184
reset(nsecs_t when)185 std::list<NotifyArgs> SensorInputMapper::reset(nsecs_t when) {
186 // Recenter all axes.
187 for (std::pair<const int32_t, Axis>& pair : mAxes) {
188 Axis& axis = pair.second;
189 axis.resetValue();
190 }
191 mHardwareTimestamp = 0;
192 mPrevMscTime = 0;
193 return InputMapper::reset(when);
194 }
195
createSensor(InputDeviceSensorType sensorType,const Axis & axis)196 SensorInputMapper::Sensor SensorInputMapper::createSensor(InputDeviceSensorType sensorType,
197 const Axis& axis) {
198 InputDeviceIdentifier identifier = getDeviceContext().getDeviceIdentifier();
199 const auto& config = getDeviceContext().getConfiguration();
200
201 std::string prefix = "sensor." + ftl::enum_string(sensorType);
202 transform(prefix.begin(), prefix.end(), prefix.begin(), ::tolower);
203
204 int32_t flags = 0;
205 std::optional<int32_t> reportingMode = config.getInt(prefix + ".reportingMode");
206 if (reportingMode.has_value()) {
207 flags |= (*reportingMode & REPORTING_MODE_MASK) << REPORTING_MODE_SHIFT;
208 }
209
210 // Sensor Id will be assigned to device Id to distinguish same sensor from multiple input
211 // devices, in such a way that the sensor Id will be same as input device Id.
212 // The sensorType is to distinguish different sensors within one device.
213 // One input device can only have 1 sensor for each sensor Type.
214 InputDeviceSensorInfo sensorInfo(identifier.name, std::to_string(identifier.vendor),
215 identifier.version, sensorType,
216 InputDeviceSensorAccuracy::ACCURACY_HIGH,
217 /*maxRange=*/axis.max, /*resolution=*/axis.scale,
218 /*power=*/config.getFloat(prefix + ".power").value_or(0.0f),
219 /*minDelay=*/config.getInt(prefix + ".minDelay").value_or(0),
220 /*fifoReservedEventCount=*/
221 config.getInt(prefix + ".fifoReservedEventCount").value_or(0),
222 /*fifoMaxEventCount=*/
223 config.getInt(prefix + ".fifoMaxEventCount").value_or(0),
224 ftl::enum_string(sensorType),
225 /*maxDelay=*/config.getInt(prefix + ".maxDelay").value_or(0),
226 /*flags=*/flags, getDeviceId());
227
228 return Sensor(sensorInfo);
229 }
230
processHardWareTimestamp(nsecs_t evTime,int32_t mscTime)231 void SensorInputMapper::processHardWareTimestamp(nsecs_t evTime, int32_t mscTime) {
232 // Since MSC_TIMESTAMP initial state is different from the system time, we
233 // calculate the difference between two MSC_TIMESTAMP events, and use that
234 // to calculate the system time that should be tagged on the event.
235 // if the first time MSC_TIMESTAMP, store it
236 // else calculate difference between previous and current MSC_TIMESTAMP
237 if (mPrevMscTime == 0) {
238 mHardwareTimestamp = evTime;
239 if (DEBUG_SENSOR_EVENT_DETAILS) {
240 ALOGD("Initialize hardware timestamp = %" PRId64, mHardwareTimestamp);
241 }
242 } else {
243 // Calculate the difference between current msc_timestamp and
244 // previous msc_timestamp, including when msc_timestamp wraps around.
245 uint32_t timeDiff = (mPrevMscTime > static_cast<uint32_t>(mscTime))
246 ? (UINT32_MAX - mPrevMscTime + static_cast<uint32_t>(mscTime + 1))
247 : (static_cast<uint32_t>(mscTime) - mPrevMscTime);
248
249 mHardwareTimestamp += timeDiff * 1000LL;
250 }
251 mPrevMscTime = static_cast<uint32_t>(mscTime);
252 }
253
process(const RawEvent & rawEvent)254 std::list<NotifyArgs> SensorInputMapper::process(const RawEvent& rawEvent) {
255 std::list<NotifyArgs> out;
256 switch (rawEvent.type) {
257 case EV_ABS: {
258 auto it = mAxes.find(rawEvent.code);
259 if (it != mAxes.end()) {
260 Axis& axis = it->second;
261 axis.newValue = rawEvent.value * axis.scale + axis.offset;
262 }
263 break;
264 }
265
266 case EV_SYN:
267 switch (rawEvent.code) {
268 case SYN_REPORT:
269 for (std::pair<const int32_t, Axis>& pair : mAxes) {
270 Axis& axis = pair.second;
271 axis.currentValue = axis.newValue;
272 }
273 out += sync(rawEvent.when, /*force=*/false);
274 break;
275 }
276 break;
277
278 case EV_MSC:
279 switch (rawEvent.code) {
280 case MSC_TIMESTAMP:
281 // hardware timestamp is nano seconds
282 processHardWareTimestamp(rawEvent.when, rawEvent.value);
283 break;
284 }
285 }
286 return out;
287 }
288
setSensorEnabled(InputDeviceSensorType sensorType,bool enabled)289 bool SensorInputMapper::setSensorEnabled(InputDeviceSensorType sensorType, bool enabled) {
290 auto it = mSensors.find(sensorType);
291 if (it == mSensors.end()) {
292 return false;
293 }
294
295 it->second.enabled = enabled;
296 if (!enabled) {
297 it->second.resetValue();
298 }
299
300 /* Currently we can't enable/disable sensors individually. Enabling any sensor will enable
301 * the device
302 */
303 mDeviceEnabled = false;
304 for (const auto& [_, sensor] : mSensors) {
305 // If any sensor is on we will turn on the device.
306 if (sensor.enabled) {
307 mDeviceEnabled = true;
308 break;
309 }
310 }
311 return true;
312 }
313
flushSensor(InputDeviceSensorType sensorType)314 void SensorInputMapper::flushSensor(InputDeviceSensorType sensorType) {
315 auto it = mSensors.find(sensorType);
316 if (it == mSensors.end()) {
317 return;
318 }
319 auto& sensor = it->second;
320 sensor.lastSampleTimeNs = 0;
321 for (size_t i = 0; i < SENSOR_VEC_LEN; i++) {
322 int32_t abs = sensor.dataVec[i];
323 auto itAxis = mAxes.find(abs);
324 if (itAxis != mAxes.end()) {
325 Axis& axis = itAxis->second;
326 axis.resetValue();
327 }
328 }
329 }
330
enableSensor(InputDeviceSensorType sensorType,std::chrono::microseconds samplingPeriod,std::chrono::microseconds maxBatchReportLatency)331 bool SensorInputMapper::enableSensor(InputDeviceSensorType sensorType,
332 std::chrono::microseconds samplingPeriod,
333 std::chrono::microseconds maxBatchReportLatency) {
334 if (DEBUG_SENSOR_EVENT_DETAILS) {
335 ALOGD("Enable Sensor %s samplingPeriod %lld maxBatchReportLatency %lld",
336 ftl::enum_string(sensorType).c_str(), samplingPeriod.count(),
337 maxBatchReportLatency.count());
338 }
339
340 if (!setSensorEnabled(sensorType, /*enabled=*/true)) {
341 return false;
342 }
343
344 // Enable device
345 if (mDeviceEnabled) {
346 getDeviceContext().enableDevice();
347 }
348
349 // We know the sensor exists now, update the sampling period and batch report latency.
350 auto it = mSensors.find(sensorType);
351 it->second.samplingPeriod =
352 std::chrono::duration_cast<std::chrono::nanoseconds>(samplingPeriod);
353 it->second.maxBatchReportLatency =
354 std::chrono::duration_cast<std::chrono::nanoseconds>(maxBatchReportLatency);
355 return true;
356 }
357
disableSensor(InputDeviceSensorType sensorType)358 void SensorInputMapper::disableSensor(InputDeviceSensorType sensorType) {
359 if (DEBUG_SENSOR_EVENT_DETAILS) {
360 ALOGD("Disable Sensor %s", ftl::enum_string(sensorType).c_str());
361 }
362
363 if (!setSensorEnabled(sensorType, /*enabled=*/false)) {
364 return;
365 }
366
367 // Disable device
368 if (!mDeviceEnabled) {
369 mHardwareTimestamp = 0;
370 mPrevMscTime = 0;
371 getDeviceContext().disableDevice();
372 }
373 }
374
sync(nsecs_t when,bool force)375 std::list<NotifyArgs> SensorInputMapper::sync(nsecs_t when, bool force) {
376 std::list<NotifyArgs> out;
377 for (auto& [sensorType, sensor] : mSensors) {
378 // Skip if sensor not enabled
379 if (!sensor.enabled) {
380 continue;
381 }
382 std::vector<float> values;
383 for (ssize_t i = 0; i < SENSOR_VEC_LEN; i++) {
384 int32_t abs = sensor.dataVec[i];
385 auto it = mAxes.find(abs);
386 if (it != mAxes.end()) {
387 const Axis& axis = it->second;
388 values.push_back(axis.currentValue);
389 }
390 }
391
392 nsecs_t timestamp = mHasHardwareTimestamp ? mHardwareTimestamp : when;
393 if (DEBUG_SENSOR_EVENT_DETAILS) {
394 ALOGD("Sensor %s timestamp %" PRIu64 " values [%f %f %f]",
395 ftl::enum_string(sensorType).c_str(), timestamp, values[0], values[1], values[2]);
396 }
397 if (sensor.lastSampleTimeNs.has_value() &&
398 timestamp - sensor.lastSampleTimeNs.value() < sensor.samplingPeriod.count()) {
399 if (DEBUG_SENSOR_EVENT_DETAILS) {
400 ALOGD("Sensor %s Skip a sample.", ftl::enum_string(sensorType).c_str());
401 }
402 } else {
403 // Convert to Android unit
404 convertFromLinuxToAndroid(values, sensorType);
405 // Notify dispatcher for sensor event
406 out.push_back(NotifySensorArgs(getContext()->getNextId(), when, getDeviceId(),
407 AINPUT_SOURCE_SENSOR, sensorType,
408 sensor.sensorInfo.accuracy,
409 /*accuracyChanged=*/sensor.accuracy !=
410 sensor.sensorInfo.accuracy,
411 /*hwTimestamp=*/timestamp, values));
412 sensor.lastSampleTimeNs = timestamp;
413 sensor.accuracy = sensor.sensorInfo.accuracy;
414 }
415 }
416 return out;
417 }
418
419 } // namespace android
420