/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <android/sensor.h>
struct SensorConfig {
int listIndex;
int type;
int32_t rate;
int64_t reportLatency;
bool receivedEvent;
};
ASensorManager *mSensorManager;
ASensorList mSensorList;
int mNumSensors;
bool mContinuousMode;
SensorConfig mSensorConfigList[16];
int mNumSensorConfigs;
void showHelp()
{
printf("Usage: sensortest [-h] [-l] [-e <type> <rate_usecs>] [-b <type> <rate_usecs> <batch_usecs>] [-c]\n");
}
void printSensorList()
{
int prevMinType = -1;
int currMinType;
int currMinIndex = 0;
printf("[Type] - Name\n");
for (int i = 0; i < mNumSensors; i++) {
currMinType = INT_MAX;
for (int j = 0; j < mNumSensors; j++) {
if ((ASensor_getType(mSensorList[j]) > prevMinType) &&
(ASensor_getType(mSensorList[j]) < currMinType)) {
currMinType = ASensor_getType(mSensorList[j]);
currMinIndex = j;
}
}
printf("[%d] = \"%s\"\n", currMinType, ASensor_getName(mSensorList[currMinIndex]));
prevMinType = currMinType;
}
}
int findSensorTypeInSensorList(int type)
{
for (int i = 0; i < mNumSensors; i++) {
if (ASensor_getType(mSensorList[i]) == type) {
return i;
}
}
return -1;
}
int findSensorTypeInConfigList(int type)
{
for (int i = 0; i < mNumSensorConfigs; i++) {
if (mSensorConfigList[i].type == type) {
return i;
}
}
return -1;
}
bool parseArguments(int argc, char **argv)
{
int currArgumentIndex = 1;
int sensorIndex;
int existingSensorConfigIndex;
mNumSensorConfigs = 0;
while (currArgumentIndex < argc) {
if (!strcmp(argv[currArgumentIndex], "-h")) {
return false;
} else if (!strcmp(argv[currArgumentIndex], "-l")) {
printSensorList();
currArgumentIndex++;
} else if (!strcmp(argv[currArgumentIndex], "-e")) {
if (currArgumentIndex + 2 >= argc) {
printf ("Not enough arguments for enable option\n");
return false;
}
if ((sensorIndex = findSensorTypeInSensorList(atoi(argv[currArgumentIndex+1]))) < 0) {
printf ("No sensor found with type \"%d\"\n", atoi(argv[currArgumentIndex+1]));
return false;
}
existingSensorConfigIndex = findSensorTypeInConfigList(atoi(argv[currArgumentIndex+1]));
if (existingSensorConfigIndex >= 0) {
printf("Replacing previous config for sensor type %d\n", atoi(argv[currArgumentIndex+1]));
mSensorConfigList[existingSensorConfigIndex] = (SensorConfig) {
.listIndex = sensorIndex,
.type = atoi(argv[currArgumentIndex+1]),
.rate = atoi(argv[currArgumentIndex+2]),
.reportLatency = 0,
.receivedEvent = false
};
} else {
mSensorConfigList[(mNumSensorConfigs)++] = (SensorConfig) {
.listIndex = sensorIndex,
.type = atoi(argv[currArgumentIndex+1]),
.rate = atoi(argv[currArgumentIndex+2]),
.reportLatency = 0,
.receivedEvent = false
};
}
currArgumentIndex += 3;
} else if (!strcmp(argv[currArgumentIndex], "-b")) {
if (currArgumentIndex + 3 >= argc) {
printf ("Not enough arguments for batch option\n");
return false;
}
if ((sensorIndex = findSensorTypeInSensorList(atoi(argv[currArgumentIndex+1]))) < 0) {
printf ("No sensor found with type \"%d\"\n", atoi(argv[currArgumentIndex+1]));
return false;
}
existingSensorConfigIndex = findSensorTypeInConfigList(atoi(argv[currArgumentIndex+1]));
if (existingSensorConfigIndex >= 0) {
printf("Replacing previous config for sensor type %d\n", atoi(argv[currArgumentIndex+1]));
mSensorConfigList[existingSensorConfigIndex] = (SensorConfig) {
.listIndex = sensorIndex,
.type = atoi(argv[currArgumentIndex+1]),
.rate = atoi(argv[currArgumentIndex+2]),
.reportLatency = atoi(argv[currArgumentIndex+3]),
.receivedEvent = false
};
} else {
mSensorConfigList[(mNumSensorConfigs)++] = (SensorConfig) {
.listIndex = sensorIndex,
.type = atoi(argv[currArgumentIndex+1]),
.rate = atoi(argv[currArgumentIndex+2]),
.reportLatency = atoi(argv[currArgumentIndex+3]),
.receivedEvent = false
};
}
currArgumentIndex += 4;
} else if (!strcmp(argv[currArgumentIndex], "-c")) {
mContinuousMode = true;
currArgumentIndex++;
} else {
printf("Invalid argument \"%s\"\n", argv[currArgumentIndex]);
return false;
}
}
return true;
}
bool hasReceivedAllEvents()
{
for (int i = 0; i < mNumSensorConfigs; i++) {
if (!mSensorConfigList[i].receivedEvent) {
return false;
}
}
return true;
};
int main(int argc, char **argv) {
int numSensorEvents;
ASensorEvent sensorEvents[16];
int configListIndex;
mSensorManager = ASensorManager_getInstanceForPackage("");
mNumSensors = ASensorManager_getSensorList(mSensorManager, &mSensorList);
if ((argc == 1) || !parseArguments(argc, argv)) {
showHelp();
return -1;
}
if (mNumSensorConfigs <= 0)
return 0;
ALooper *mLooper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
ASensorEventQueue *sensorEventQueue = ASensorManager_createEventQueue(mSensorManager, mLooper, 0, NULL, NULL);
for (int i = 0; i < mNumSensorConfigs; i++) {
if (ASensorEventQueue_registerSensor(sensorEventQueue, mSensorList[mSensorConfigList[i].listIndex],
mSensorConfigList[i].rate, mSensorConfigList[i].reportLatency) < 0) {
printf("Unable to register sensor %d with rate %d and report latency %" PRId64 "\n",
mSensorConfigList[i].listIndex, mSensorConfigList[i].rate,
mSensorConfigList[i].reportLatency);
}
}
while (mContinuousMode || !hasReceivedAllEvents()) {
if ((numSensorEvents = ASensorEventQueue_getEvents(sensorEventQueue, sensorEvents, 16)) < 0) {
printf("An error occurred while polling for events\n");
break;
} else if (numSensorEvents > 0) {
for (int i = 0; i < numSensorEvents; i++) {
if ((configListIndex = findSensorTypeInConfigList(sensorEvents[i].type)) < 0) {
printf("Received unexpected event for type %d\n", sensorEvents[i].type);
break;
}
if (mContinuousMode || !mSensorConfigList[configListIndex].receivedEvent) {
printf("[%d] = %f, %f, %f @ %" PRId64 "\n", sensorEvents[i].type,
sensorEvents[i].data[0], sensorEvents[i].data[1],
sensorEvents[i].data[2], sensorEvents[i].timestamp);
mSensorConfigList[configListIndex].receivedEvent = true;
if (!mContinuousMode) {
ASensorEventQueue_disableSensor(sensorEventQueue, mSensorList[mSensorConfigList[configListIndex].listIndex]);
}
}
}
}
fflush(stdout);
}
ASensorManager_destroyEventQueue(mSensorManager, sensorEventQueue);
return 0;
}