Android Sensor Integration Part 4: The Android Sensor Framework

In this conclusion of our series on Android Sensor Integration we finally arrive at the Android Sensor Framework to which we are going to connect our ultrasonic range sensor. Click to dive right in or read the previous parts first for context.

Let’s go on to the second part in HAL, implementing the sensors.cpp file. This is where we connect our implementation to the existing Sensor Framework. Google published good documentation for most of the functions in sensors.cpp. But as the Pandaboard I used for this project has no sensors itself, my Android sources are missing the libsensors file—we’re gonna have to write it ourselves. Most of the functions and parts are standard implementations so they can be adopted from others.

If however your device has something like a libsensors file  there is no need to write a new one—Just add the new entries. Below we will take a look at the parts we need to add.

The sensor_t structure: letting Android know about the new sensor

For starters we look at an ordinary structure of particular importance. The sensors_t structure lets Android know about all available sensors. For each sensor we need to add an entry with a name, vendor, version, handle, type, maximum range, resolution, power, minimum delay and a few more properties. In the sensor.h all parameters and their meanings are described in more detail.

What about the sensors_poll_context_t structure?

Most interesting in the sensors.cpp file is a strange structure called sensors_poll_context_t. It can be misused as a class as it defines both public and private variables and functions.

We use these functions accessing the ProximitySensor class as a layer between the sensor itself and the functions in the sensors.h interface we need to define. The private declarations inside the this structure start with the definition of enumerations. We need to add one for the proximity sensor:

In the private part of this struct the function handleToDriver is defined. We need to add a classification from the proximity handle ID_PX to the enum we defined. In the sensors library of the Pandaboard we just have this one sensor, so it is returned as default.

Let’s take a look at the functions declared in this structure. For each function sensors.h is requesting, we have a corresponding function defined in it. Except for the batch() and flush() functions there is no equivalent.

Batching means storing sensor events in a hardware FIFO stack before reporting, but our sensor’s hardware does not support this. Other than that each call to a poll__ function is forwarded to the sensors_poll_context_t functions. The open_sensors() function corresponds to the structure’s constructor.

So let’s continue to this constructor. In this part we create a new instance of the ProximitySensor class as an entry in the SensorBase typed array. We also set the entries for our sensor in mPollFds, an array based on the structure pollfd. Its member fd holds the file descriptor of the ProximitySensor instance. While the member events stands for an input event flag, revents  names output event flags. Thus  POLLIN allows data or high-priority data to be read without blocking.

Finally we look at the pollEvents() function. We have nothing to add to it but it is still an interesting part, as the values are fed into the framework here. This function reads the events of every registered sensor and stores the data in the data-pointer. In the first part—in the do-while-loop—, we look for data we have left over from the last call of the poll() function. With if (count) we are able to find out whether there is space to store a few more values. If there is we try to fetch some events immediately. Or we wait if there is nothing to return.

As long as we have events and space to save them, this loop goes on.

If everything works correctly, every single app with permissions for the proximity sensor can now also access our new sensor.

Android proximity sensor app

A simple app I wrote to test the sensor’s readings. It works!

Sources (Parts 3 and 4)

Get in touch

And that’s a wrap! I hope you enjoyed our deep dive into Android Sensor Integration and you got a good impression of the complexity of such a diminutive device as well as the roles the kernel and HAL play in its integration. If you have any questions feel free to leave a comment below. If you liked our articles please share them. For more information on embedded development and the IoT visit our website or call us at +49 721 619 021-0.

The Whole Story

comments powered by Disqus