• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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