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 ALOGD_IF(DEBUG_SENSOR_EVENT_DETAILS, "Initialize hardware timestamp = %" PRId64,
239 mHardwareTimestamp);
240 } else {
241 // Calculate the difference between current msc_timestamp and
242 // previous msc_timestamp, including when msc_timestamp wraps around.
243 uint32_t timeDiff = (mPrevMscTime > static_cast<uint32_t>(mscTime))
244 ? (UINT32_MAX - mPrevMscTime + static_cast<uint32_t>(mscTime + 1))
245 : (static_cast<uint32_t>(mscTime) - mPrevMscTime);
246
247 mHardwareTimestamp += timeDiff * 1000LL;
248 }
249 mPrevMscTime = static_cast<uint32_t>(mscTime);
250 }
251
process(const RawEvent & rawEvent)252 std::list<NotifyArgs> SensorInputMapper::process(const RawEvent& rawEvent) {
253 std::list<NotifyArgs> out;
254 switch (rawEvent.type) {
255 case EV_ABS: {
256 auto it = mAxes.find(rawEvent.code);
257 if (it != mAxes.end()) {
258 Axis& axis = it->second;
259 axis.newValue = rawEvent.value * axis.scale + axis.offset;
260 }
261 break;
262 }
263
264 case EV_SYN:
265 switch (rawEvent.code) {
266 case SYN_REPORT:
267 for (std::pair<const int32_t, Axis>& pair : mAxes) {
268 Axis& axis = pair.second;
269 axis.currentValue = axis.newValue;
270 }
271 out += sync(rawEvent.when, /*force=*/false);
272 break;
273 }
274 break;
275
276 case EV_MSC:
277 switch (rawEvent.code) {
278 case MSC_TIMESTAMP:
279 // hardware timestamp is nano seconds
280 processHardWareTimestamp(rawEvent.when, rawEvent.value);
281 break;
282 }
283 }
284 return out;
285 }
286
setSensorEnabled(InputDeviceSensorType sensorType,bool enabled)287 bool SensorInputMapper::setSensorEnabled(InputDeviceSensorType sensorType, bool enabled) {
288 auto it = mSensors.find(sensorType);
289 if (it == mSensors.end()) {
290 return false;
291 }
292
293 it->second.enabled = enabled;
294 if (!enabled) {
295 it->second.resetValue();
296 }
297
298 /* Currently we can't enable/disable sensors individually. Enabling any sensor will enable
299 * the device
300 */
301 mDeviceEnabled = false;
302 for (const auto& [_, sensor] : mSensors) {
303 // If any sensor is on we will turn on the device.
304 if (sensor.enabled) {
305 mDeviceEnabled = true;
306 break;
307 }
308 }
309 return true;
310 }
311
flushSensor(InputDeviceSensorType sensorType)312 void SensorInputMapper::flushSensor(InputDeviceSensorType sensorType) {
313 auto it = mSensors.find(sensorType);
314 if (it == mSensors.end()) {
315 return;
316 }
317 auto& sensor = it->second;
318 sensor.lastSampleTimeNs = 0;
319 for (size_t i = 0; i < SENSOR_VEC_LEN; i++) {
320 int32_t abs = sensor.dataVec[i];
321 auto itAxis = mAxes.find(abs);
322 if (itAxis != mAxes.end()) {
323 Axis& axis = itAxis->second;
324 axis.resetValue();
325 }
326 }
327 }
328
enableSensor(InputDeviceSensorType sensorType,std::chrono::microseconds samplingPeriod,std::chrono::microseconds maxBatchReportLatency)329 bool SensorInputMapper::enableSensor(InputDeviceSensorType sensorType,
330 std::chrono::microseconds samplingPeriod,
331 std::chrono::microseconds maxBatchReportLatency) {
332 ALOGD_IF(DEBUG_SENSOR_EVENT_DETAILS,
333 "Enable Sensor %s samplingPeriod %lld maxBatchReportLatency %lld",
334 ftl::enum_string(sensorType).c_str(), samplingPeriod.count(),
335 maxBatchReportLatency.count());
336
337 if (!setSensorEnabled(sensorType, /*enabled=*/true)) {
338 return false;
339 }
340
341 // Enable device
342 if (mDeviceEnabled) {
343 getDeviceContext().enableDevice();
344 }
345
346 // We know the sensor exists now, update the sampling period and batch report latency.
347 auto it = mSensors.find(sensorType);
348 it->second.samplingPeriod =
349 std::chrono::duration_cast<std::chrono::nanoseconds>(samplingPeriod);
350 it->second.maxBatchReportLatency =
351 std::chrono::duration_cast<std::chrono::nanoseconds>(maxBatchReportLatency);
352 return true;
353 }
354
disableSensor(InputDeviceSensorType sensorType)355 void SensorInputMapper::disableSensor(InputDeviceSensorType sensorType) {
356 ALOGD_IF(DEBUG_SENSOR_EVENT_DETAILS, "Disable Sensor %s", ftl::enum_string(sensorType).c_str());
357
358 if (!setSensorEnabled(sensorType, /*enabled=*/false)) {
359 return;
360 }
361
362 // Disable device
363 if (!mDeviceEnabled) {
364 mHardwareTimestamp = 0;
365 mPrevMscTime = 0;
366 getDeviceContext().disableDevice();
367 }
368 }
369
sync(nsecs_t when,bool force)370 std::list<NotifyArgs> SensorInputMapper::sync(nsecs_t when, bool force) {
371 std::list<NotifyArgs> out;
372 for (auto& [sensorType, sensor] : mSensors) {
373 // Skip if sensor not enabled
374 if (!sensor.enabled) {
375 continue;
376 }
377 std::vector<float> values;
378 for (ssize_t i = 0; i < SENSOR_VEC_LEN; i++) {
379 int32_t abs = sensor.dataVec[i];
380 auto it = mAxes.find(abs);
381 if (it != mAxes.end()) {
382 const Axis& axis = it->second;
383 values.push_back(axis.currentValue);
384 }
385 }
386
387 nsecs_t timestamp = mHasHardwareTimestamp ? mHardwareTimestamp : when;
388 ALOGD_IF(DEBUG_SENSOR_EVENT_DETAILS, "Sensor %s timestamp %" PRIu64 " values [%f %f %f]",
389 ftl::enum_string(sensorType).c_str(), timestamp, values[0], values[1], values[2]);
390 if (sensor.lastSampleTimeNs.has_value() &&
391 timestamp - sensor.lastSampleTimeNs.value() < sensor.samplingPeriod.count()) {
392 ALOGD_IF(DEBUG_SENSOR_EVENT_DETAILS, "Sensor %s Skip a sample.",
393 ftl::enum_string(sensorType).c_str());
394 } else {
395 // Convert to Android unit
396 convertFromLinuxToAndroid(values, sensorType);
397 // Notify dispatcher for sensor event
398 out.push_back(NotifySensorArgs(getContext()->getNextId(), when, getDeviceId(),
399 AINPUT_SOURCE_SENSOR, sensorType,
400 sensor.sensorInfo.accuracy,
401 /*accuracyChanged=*/sensor.accuracy !=
402 sensor.sensorInfo.accuracy,
403 /*hwTimestamp=*/timestamp, values));
404 sensor.lastSampleTimeNs = timestamp;
405 sensor.accuracy = sensor.sensorInfo.accuracy;
406 }
407 }
408 return out;
409 }
410
411 } // namespace android
412