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