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