diff options
author | Mohammed Habibulla <moch@google.com> | 2016-01-04 22:25:01 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2016-01-04 22:25:01 +0000 |
commit | 45f90b9eb2439be5a3664ab26c36bab7d2057c8f (patch) | |
tree | 3e17d7575010e42619925bcb216eb97d3284f0da | |
parent | 8eb9e0bcb326b2b4fa8c104451603bf07a926d16 (diff) | |
parent | 71737fb913bb95fba3cac000d1dcc8d8d9d41344 (diff) | |
download | common-brillo-m9-release.tar.gz |
Merge "sensors:ndk-example-app: rewrite to work with multiple sensors"brillo-m9-releasebrillo-m9-dev
-rw-r--r-- | sensors_example/ndk-example-app.cpp | 263 |
1 files changed, 188 insertions, 75 deletions
diff --git a/sensors_example/ndk-example-app.cpp b/sensors_example/ndk-example-app.cpp index 78b13ad..628068d 100644 --- a/sensors_example/ndk-example-app.cpp +++ b/sensors_example/ndk-example-app.cpp @@ -14,117 +14,230 @@ * limitations under the License. */ -// This file contains an example app that uses sensors NDK API. +/* This file contains an example app that uses sensors NDK. + * It accepts a sensor type as an input argument and reads data from a + * sensor of that type. + * + * For any specified sensor type, there may be multiple such sensors defined + * in the HAL. Some or all of the defined sensors will actually be equipped. + * This test program will scan the HAL for the first equipped sensor of + * the specified sensor type and dump data from that sensor. + */ +#include <getopt.h> +#include <math.h> #include <stdio.h> #include <string.h> #include <unistd.h> -#include <map> -#include <string> - #include <android/looper.h> #include <android/sensor.h> #include <hardware/sensors.h> -const char kPackageName[] = "ndk-example-app"; -const int kLooperId = 1; +#define DEFAULT_SENSOR_TYPE SENSOR_TYPE_ACCELEROMETER + +// Structure to hold the decoded command line options +struct pgm_options { + int sensor_type; +}; + +// Be sure to keep the options for longopts and shortopts in the same order +// so that Usage() is correct. +static struct option longopts[] = { + {"help", no_argument, NULL, '?'}, + {"accel", no_argument, NULL, 'a'}, + {"temp", no_argument, NULL, 't'}, + {"light", no_argument, NULL, 'l'}, + {"orient", no_argument, NULL, 'o'}, + {"prox", no_argument, NULL, 'p'}, + {"motion", no_argument, NULL, 'm'}, + {NULL, 0, NULL, 0} +}; +static char shortopts[] = "?atlopm"; + +// Describes the options for this program. +void Usage(char *pgm_name) { + printf("Usage: %s [options...]\n", pgm_name); + printf("Exercises the sensors NDK by calling into the sensorserver.\n"); + printf("Options:\n"); + for (int i = 0; longopts[i].name; i++) { + printf(" --%-6s or -%c\n", longopts[i].name, shortopts[i]); + } +} + +// Processes all command line options. +// sets the options members for commnd line options +// returns (0) on success, -1 otherwise. +int ReadOpts(int argc, char **argv, struct pgm_options *options) { + int ch = 0; + + if (!options) { + fprintf(stderr, "Invalid options pointer\n"); + return 1; + } + + while ((ch = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) { + switch (ch) { + case 'a': + options->sensor_type = SENSOR_TYPE_ACCELEROMETER; + break; + case 't': + options->sensor_type = SENSOR_TYPE_TEMPERATURE; + break; + case 'l': + options->sensor_type = SENSOR_TYPE_LIGHT; + break; + case 'o': + options->sensor_type = SENSOR_TYPE_ORIENTATION; + break; + case 'p': + options->sensor_type = SENSOR_TYPE_PROXIMITY; + break; + case 'm': + options->sensor_type = SENSOR_TYPE_SIGNIFICANT_MOTION; + break; + default: + Usage(argv[0]); + return -1; + } + } + argc -= optind; + argv += optind; + return 0; +} + +// Prints data associated with each supported sensor type. +// Be sure to provide a case for each sensor type supported in +// the ReadOpts() function. +void DisplaySensorData(int sensor_type, const ASensorEvent *data) { + switch (sensor_type) { + case SENSOR_TYPE_PROXIMITY: + printf("Proximity distance: %f\n", data->distance); + break; + case SENSOR_TYPE_SIGNIFICANT_MOTION: + if (data->data[0] == 1) { + printf("Significant motion detected\n"); + } + break; + case SENSOR_TYPE_ACCELEROMETER: + printf("Acceleration: x = %f, y = %f, z = %f\n", + data->acceleration.x, data->acceleration.y, data->acceleration.z); + break; + case SENSOR_TYPE_TEMPERATURE: + printf("Temperature: %f\n", data->temperature); + break; + case SENSOR_TYPE_LIGHT: + printf("Light: %f\n", data->light); + break; + case SENSOR_TYPE_ORIENTATION: { + float heading = + atan2(static_cast<double>(data->magnetic.y), + static_cast<double>(data->magnetic.x)) * 180.0 / M_PI; + if (heading < 0.0) + heading += 360.0; + printf("Heading: %f, Orientation: x = %f, y = %f, z = %f\n", + heading, data->magnetic.x, data->magnetic.y, data->magnetic.z); + } + break; + } +} int main(int argc, char* argv[]) { + pgm_options options = {DEFAULT_SENSOR_TYPE}; + if (ReadOpts(argc, argv, &options) < 0) + return 1; + + const char kPackageName[] = "ndk-example-app"; ASensorManager* sensor_manager = - ASensorManager_getInstanceForPackage(kPackageName); + ASensorManager_getInstanceForPackage(kPackageName); if (!sensor_manager) { fprintf(stderr, "Failed to get a sensor manager\n"); return 1; } - ASensorList sensor_list; + ASensorList sensor_list = nullptr; int sensor_count = ASensorManager_getSensorList(sensor_manager, &sensor_list); - printf("Found %d sensors\n", sensor_count); + printf("Found %d supported sensors\n", sensor_count); for (int i = 0; i < sensor_count; i++) { - printf("Found %s\n", ASensor_getName(sensor_list[i])); + printf("HAL supports sensor %s\n", ASensor_getName(sensor_list[i])); } + const int kLooperId = 1; ASensorEventQueue* queue = ASensorManager_createEventQueue( sensor_manager, ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS), - kLooperId, NULL /* no callback */, NULL /* no data */); + kLooperId, + NULL, /* no callback */ + NULL /* no private data for a callback */); if (!queue) { fprintf(stderr, "Failed to create a sensor event queue\n"); return 1; } - const std::map<int, std::string> kSensorSamples = { - /* - * Accelerometer: - * Reporting mode: continuous. Events are generated continuously. - */ - { SENSOR_TYPE_ACCELEROMETER, "accelerometer" }, - - /* - * Proximity sensor: - * Reporting mode: on-change. Events are generated only when proximity - * value has changed. - */ - { SENSOR_TYPE_PROXIMITY, "proximity sensor" }, - - /* - * Significant motion sensor: - * Reporting mode: one-shot. An event is generated when significant - * motion is detected. After that, the sensor will be disabled by - * itself. - */ - { SENSOR_TYPE_SIGNIFICANT_MOTION, "significant motion sensor" }, - }; + // Find the first sensor of the specified type that can be opened + const int kTimeoutMicroSecs = 1000000; + const int kTimeoutMilliSecs = 1000; + ASensorRef sensor = nullptr; + bool sensor_found = false; + for (int i = 0; i < sensor_count; i++) { + sensor = sensor_list[i]; + if (ASensor_getType(sensor) != options.sensor_type) + continue; + if (ASensorEventQueue_enableSensor(queue, sensor) < 0) + continue; + if (ASensorEventQueue_setEventRate(queue, sensor, kTimeoutMicroSecs) < 0) { + fprintf(stderr, "Failed to set the %s sample rate\n", + ASensor_getName(sensor)); + return 1; + } + + // Found an equipped sensor of the specified type. + sensor_found = true; + break; + } + + if (!sensor_found) { + fprintf(stderr, "No sensor of the specified type found\n"); + int ret = ASensorManager_destroyEventQueue(sensor_manager, queue); + if (ret < 0) + fprintf(stderr, "Failed to destroy event queue: %s\n", strerror(-ret)); + return 1; + } + printf("\nSensor %s activated\n", ASensor_getName(sensor)); - const int kNumSamples = 10; const int kNumEvents = 1; - const int kTimeoutMilliSecs = 1000; + const int kNumSamples = 10; const int kWaitTimeSecs = 1; + for (int i = 0; i < kNumSamples; i++) { + ASensorEvent data[kNumEvents]; + memset(data, 0, sizeof(data)); + int ident = ALooper_pollAll( + kTimeoutMilliSecs, + NULL /* no output file descriptor */, + NULL /* no output event */, + NULL /* no output data */); + if (ident != kLooperId) { + fprintf(stderr, "Incorrect Looper ident read from poll.\n"); + continue; + } + if (ASensorEventQueue_getEvents(queue, data, kNumEvents) <= 0) { + fprintf(stderr, "Failed to read data from the sensor.\n"); + continue; + } - for (auto& sensor_type : kSensorSamples) { - const ASensor* sensor = ASensorManager_getDefaultSensor(sensor_manager, - sensor_type.first); - if (sensor && !ASensorEventQueue_enableSensor(queue, sensor)) { - for (int i = 0; i < kNumSamples; i++) { - int ident = ALooper_pollAll(kTimeoutMilliSecs, - NULL /* no output file descriptor */, - NULL /* no output event */, - NULL /* no output data */); - if (ident == kLooperId) { - ASensorEvent data; - if (ASensorEventQueue_getEvents(queue, &data, kNumEvents)) { - if (sensor_type.first == SENSOR_TYPE_ACCELEROMETER) { - printf("Acceleration: x = %f, y = %f, z = %f\n", - data.acceleration.x, data.acceleration.y, - data.acceleration.z); - } else if (sensor_type.first == SENSOR_TYPE_PROXIMITY) { - printf("Proximity distance: %f\n", data.distance); - } else if (sensor_type.first == SENSOR_TYPE_SIGNIFICANT_MOTION) { - if (data.data[0] == 1) { - printf("Significant motion detected\n"); - break; - } - } - } - } - sleep(kWaitTimeSecs); - } + DisplaySensorData(options.sensor_type, data); + sleep(kWaitTimeSecs); + } - int ret = ASensorEventQueue_disableSensor(queue, sensor); - if (ret) { - fprintf(stderr, "Failed to disable %s: %s\n", - sensor_type.second.c_str(), strerror(ret)); - } - } else { - fprintf(stderr, "No %s found or failed to enable it\n", - sensor_type.second.c_str()); - } + int ret = ASensorEventQueue_disableSensor(queue, sensor); + if (ret < 0) { + fprintf(stderr, "Failed to disable %s: %s\n", + ASensor_getName(sensor), strerror(-ret)); } - int ret = ASensorManager_destroyEventQueue(sensor_manager, queue); - if (ret) { - fprintf(stderr, "Failed to destroy event queue: %s\n", strerror(ret)); + ret = ASensorManager_destroyEventQueue(sensor_manager, queue); + if (ret < 0) { + fprintf(stderr, "Failed to destroy event queue: %s\n", strerror(-ret)); return 1; } |