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