diff options
author | 2020-03-20 10:46:15 -0400 | |
---|---|---|
committer | 2020-04-17 13:34:29 -0400 | |
commit | 0ff158f8f2e5749737c51444b9aeb153bd0b325d (patch) | |
tree | 10e707f0416b83c69c973609ca62e5810df17eb2 | |
parent | fcf9aeceb7e5ea2142f347e7575c649cd291768d (diff) |
Use resolution to round sensor event values
Add method to utilize a sensor's specified resolution value to ensure
data isn't provided that is more fine-grained than expected. This
helps mitigate sensor calibration fingerprinting attacks.
Bug: 147725937
Test: Verify accel sensor data isn't more fine grained than its
specified resolution
Change-Id: I81905cde22cc8429021ffb8318a222512ce01900
-rw-r--r-- | services/sensorservice/SensorDevice.cpp | 31 | ||||
-rw-r--r-- | services/sensorservice/SensorDevice.h | 4 | ||||
-rw-r--r-- | services/sensorservice/SensorDeviceUtils.cpp | 96 | ||||
-rw-r--r-- | services/sensorservice/SensorDeviceUtils.h | 7 |
4 files changed, 135 insertions, 3 deletions
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp index 3b68e0e097..aa6f1b8f5a 100644 --- a/services/sensorservice/SensorDevice.cpp +++ b/services/sensorservice/SensorDevice.cpp @@ -143,6 +143,14 @@ void SensorDevice::initializeSensorList() { for (size_t i=0 ; i < count; i++) { sensor_t sensor; convertToSensor(convertToOldSensorInfo(list[i]), &sensor); + + if (sensor.resolution == 0) { + // Don't crash here or the device will go into a crashloop. + ALOGE("%s must have a non-zero resolution", sensor.name); + // For simple algos, map their resolution to 1 if it's not specified + sensor.resolution = SensorDeviceUtils::defaultResolutionForType(sensor.type); + } + // Sanity check and clamp power if it is 0 (or close) if (sensor.power < minPowerMa) { ALOGI("Reported power %f not deemed sane, clamping to %f", @@ -508,7 +516,7 @@ ssize_t SensorDevice::pollHal(sensors_event_t* buffer, size_t count) { const auto &events, const auto &dynamicSensorsAdded) { if (result == Result::OK) { - convertToSensorEvents(convertToNewEvents(events), + convertToSensorEventsAndQuantize(convertToNewEvents(events), convertToNewSensorInfos(dynamicSensorsAdded), buffer); err = (ssize_t)events.size(); } else { @@ -571,6 +579,8 @@ ssize_t SensorDevice::pollFmq(sensors_event_t* buffer, size_t maxNumEventsToRead for (size_t i = 0; i < eventsToRead; i++) { convertToSensorEvent(mEventBuffer[i], &buffer[i]); + android::SensorDeviceUtils::quantizeSensorEventValues(&buffer[i], + getResolutionForSensor(buffer[i].sensor)); } eventsRead = eventsToRead; } else { @@ -1077,7 +1087,7 @@ void SensorDevice::convertToSensorEvent( } } -void SensorDevice::convertToSensorEvents( +void SensorDevice::convertToSensorEventsAndQuantize( const hidl_vec<Event> &src, const hidl_vec<SensorInfo> &dynamicSensorsAdded, sensors_event_t *dst) { @@ -1088,7 +1098,24 @@ void SensorDevice::convertToSensorEvents( for (size_t i = 0; i < src.size(); ++i) { V2_1::implementation::convertToSensorEvent(src[i], &dst[i]); + android::SensorDeviceUtils::quantizeSensorEventValues(&dst[i], + getResolutionForSensor(dst[i].sensor)); + } +} + +float SensorDevice::getResolutionForSensor(int sensorHandle) { + for (size_t i = 0; i < mSensorList.size(); i++) { + if (sensorHandle == mSensorList[i].handle) { + return mSensorList[i].resolution; + } } + + auto it = mConnectedDynamicSensors.find(sensorHandle); + if (it != mConnectedDynamicSensors.end()) { + return it->second->resolution; + } + + return 0; } void SensorDevice::handleHidlDeath(const std::string & detail) { diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h index 24d03c63c2..04e60315b4 100644 --- a/services/sensorservice/SensorDevice.h +++ b/services/sensorservice/SensorDevice.h @@ -233,11 +233,13 @@ private: void convertToSensorEvent(const Event &src, sensors_event_t *dst); - void convertToSensorEvents( + void convertToSensorEventsAndQuantize( const hardware::hidl_vec<Event> &src, const hardware::hidl_vec<SensorInfo> &dynamicSensorsAdded, sensors_event_t *dst); + float getResolutionForSensor(int sensorHandle); + bool mIsDirectReportSupported; typedef hardware::MessageQueue<uint32_t, hardware::kSynchronizedReadWrite> WakeLockQueue; diff --git a/services/sensorservice/SensorDeviceUtils.cpp b/services/sensorservice/SensorDeviceUtils.cpp index dbafffe303..6bf62e4f82 100644 --- a/services/sensorservice/SensorDeviceUtils.cpp +++ b/services/sensorservice/SensorDeviceUtils.cpp @@ -17,16 +17,112 @@ #include "SensorDeviceUtils.h" #include <android/hardware/sensors/1.0/ISensors.h> +#include <android/hardware/sensors/2.1/ISensors.h> #include <utils/Log.h> #include <chrono> +#include <cmath> #include <thread> using ::android::hardware::Void; +using SensorTypeV2_1 = android::hardware::sensors::V2_1::SensorType; using namespace android::hardware::sensors::V1_0; namespace android { namespace SensorDeviceUtils { +namespace { + +inline void quantizeValue(float *value, double resolution) { + // Increase the value of the sensor's nominal resolution to ensure that + // sensor accuracy improvements, like runtime calibration, are not masked + // during requantization. + double incRes = 0.25 * resolution; + *value = round(static_cast<double>(*value) / incRes) * incRes; +} + +} // namespace + +void quantizeSensorEventValues(sensors_event_t *event, float resolution) { + LOG_FATAL_IF(resolution == 0, "Resolution must be specified for all sensors!"); + if (resolution == 0) { + return; + } + + size_t axes = 0; + switch ((SensorTypeV2_1)event->type) { + case SensorTypeV2_1::ACCELEROMETER: + case SensorTypeV2_1::MAGNETIC_FIELD: + case SensorTypeV2_1::ORIENTATION: + case SensorTypeV2_1::GYROSCOPE: + case SensorTypeV2_1::GRAVITY: + case SensorTypeV2_1::LINEAR_ACCELERATION: + case SensorTypeV2_1::MAGNETIC_FIELD_UNCALIBRATED: + case SensorTypeV2_1::GYROSCOPE_UNCALIBRATED: + case SensorTypeV2_1::ACCELEROMETER_UNCALIBRATED: + axes = 3; + break; + case SensorTypeV2_1::GAME_ROTATION_VECTOR: + axes = 4; + break; + case SensorTypeV2_1::ROTATION_VECTOR: + case SensorTypeV2_1::GEOMAGNETIC_ROTATION_VECTOR: + axes = 5; + break; + case SensorTypeV2_1::DEVICE_ORIENTATION: + case SensorTypeV2_1::LIGHT: + case SensorTypeV2_1::PRESSURE: + case SensorTypeV2_1::TEMPERATURE: + case SensorTypeV2_1::PROXIMITY: + case SensorTypeV2_1::RELATIVE_HUMIDITY: + case SensorTypeV2_1::AMBIENT_TEMPERATURE: + case SensorTypeV2_1::SIGNIFICANT_MOTION: + case SensorTypeV2_1::STEP_DETECTOR: + case SensorTypeV2_1::TILT_DETECTOR: + case SensorTypeV2_1::WAKE_GESTURE: + case SensorTypeV2_1::GLANCE_GESTURE: + case SensorTypeV2_1::PICK_UP_GESTURE: + case SensorTypeV2_1::WRIST_TILT_GESTURE: + case SensorTypeV2_1::STATIONARY_DETECT: + case SensorTypeV2_1::MOTION_DETECT: + case SensorTypeV2_1::HEART_BEAT: + case SensorTypeV2_1::LOW_LATENCY_OFFBODY_DETECT: + case SensorTypeV2_1::HINGE_ANGLE: + axes = 1; + break; + case SensorTypeV2_1::POSE_6DOF: + axes = 15; + break; + default: + // No other sensors have data that needs to be rounded. + break; + } + + // sensor_event_t is a union so we're able to perform the same quanitization action for most + // sensors by only knowing the number of axes their output data has. + for (size_t i = 0; i < axes; i++) { + quantizeValue(&event->data[i], resolution); + } +} + +float defaultResolutionForType(int type) { + switch ((SensorTypeV2_1)type) { + case SensorTypeV2_1::SIGNIFICANT_MOTION: + case SensorTypeV2_1::STEP_DETECTOR: + case SensorTypeV2_1::STEP_COUNTER: + case SensorTypeV2_1::TILT_DETECTOR: + case SensorTypeV2_1::WAKE_GESTURE: + case SensorTypeV2_1::GLANCE_GESTURE: + case SensorTypeV2_1::PICK_UP_GESTURE: + case SensorTypeV2_1::WRIST_TILT_GESTURE: + case SensorTypeV2_1::STATIONARY_DETECT: + case SensorTypeV2_1::MOTION_DETECT: + return 1.0f; + default: + // fall through and return 0 for all other types + break; + } + return 0.0f; +} HidlServiceRegistrationWaiter::HidlServiceRegistrationWaiter() { } diff --git a/services/sensorservice/SensorDeviceUtils.h b/services/sensorservice/SensorDeviceUtils.h index e2eb606b9a..b66542cd09 100644 --- a/services/sensorservice/SensorDeviceUtils.h +++ b/services/sensorservice/SensorDeviceUtils.h @@ -18,6 +18,7 @@ #define ANDROID_SENSOR_DEVICE_UTIL #include <android/hidl/manager/1.0/IServiceNotification.h> +#include <hardware/sensors.h> #include <condition_variable> #include <thread> @@ -29,6 +30,12 @@ using ::android::hidl::manager::V1_0::IServiceNotification; namespace android { namespace SensorDeviceUtils { +// Ensures a sensor event doesn't provide values finer grained than its sensor resolution allows. +void quantizeSensorEventValues(sensors_event_t *event, float resolution); + +// Provides a default resolution for simple sensor types if one wasn't provided by the HAL. +float defaultResolutionForType(int type); + class HidlServiceRegistrationWaiter : public IServiceNotification { public: |