1 /*
2  * Copyright (C) 2016 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 <inttypes.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <unistd.h>
22 
23 #include <android/sensor.h>
24 
25 struct SensorConfig {
26     int listIndex;
27     int type;
28     int32_t rate;
29     int reportLatency;
30     bool receivedEvent;
31 };
32 
33 
34 ASensorManager *mSensorManager;
35 ASensorList mSensorList;
36 int mNumSensors;
37 bool mContinuousMode;
38 SensorConfig mSensorConfigList[16];
39 int mNumSensorConfigs;
40 
showHelp()41 void showHelp()
42 {
43     printf("Usage: sensortest [-h] [-l] [-e <type> <rate_usecs>] [-b <type> <rate_usecs> <batch_usecs>] [-c]\n");
44 }
45 
printSensorList()46 void printSensorList()
47 {
48     int prevMinType = -1;
49     int currMinType;
50     int currMinIndex = 0;
51 
52     printf("[Type] - Name\n");
53 
54     for (int i = 0; i < mNumSensors; i++) {
55         currMinType = INT_MAX;
56 
57         for (int j = 0; j < mNumSensors; j++) {
58             if ((ASensor_getType(mSensorList[j]) > prevMinType) &&
59                 (ASensor_getType(mSensorList[j]) < currMinType)) {
60                 currMinType = ASensor_getType(mSensorList[j]);
61                 currMinIndex = j;
62             }
63         }
64 
65         printf("[%d] = \"%s\"\n", currMinType, ASensor_getName(mSensorList[currMinIndex]));
66 
67         prevMinType = currMinType;
68     }
69 }
70 
findSensorTypeInSensorList(int type)71 int findSensorTypeInSensorList(int type)
72 {
73     for (int i = 0; i < mNumSensors; i++) {
74         if (ASensor_getType(mSensorList[i]) == type) {
75             return i;
76         }
77     }
78 
79     return -1;
80 }
81 
findSensorTypeInConfigList(int type)82 int findSensorTypeInConfigList(int type)
83 {
84     for (int i = 0; i < mNumSensorConfigs; i++) {
85         if (mSensorConfigList[i].type == type) {
86             return i;
87         }
88     }
89 
90     return -1;
91 }
92 
parseArguments(int argc,char ** argv)93 bool parseArguments(int argc, char **argv)
94 {
95     int currArgumentIndex = 1;
96     int sensorIndex;
97     int existingSensorConfigIndex;
98 
99     mNumSensorConfigs = 0;
100 
101     while (currArgumentIndex < argc) {
102         if (!strcmp(argv[currArgumentIndex], "-h")) {
103             return false;
104         } else if (!strcmp(argv[currArgumentIndex], "-l")) {
105             printSensorList();
106             currArgumentIndex++;
107         } else if (!strcmp(argv[currArgumentIndex], "-e")) {
108             if (currArgumentIndex + 2 >= argc) {
109                 printf ("Not enough arguments for enable option\n");
110                 return false;
111             }
112 
113             if ((sensorIndex = findSensorTypeInSensorList(atoi(argv[currArgumentIndex+1]))) < 0) {
114                 printf ("No sensor found with type \"%d\"\n", atoi(argv[currArgumentIndex+1]));
115                 return false;
116             }
117 
118             existingSensorConfigIndex = findSensorTypeInConfigList(atoi(argv[currArgumentIndex+1]));
119 
120             if (existingSensorConfigIndex >= 0) {
121                 printf("Replacing previous config for sensor type %d\n", atoi(argv[currArgumentIndex+1]));
122                 mSensorConfigList[existingSensorConfigIndex] = {
123                     .listIndex = sensorIndex,
124                     .type = atoi(argv[currArgumentIndex+1]),
125                     .rate = atoi(argv[currArgumentIndex+2]),
126                     .reportLatency = 0,
127                     .receivedEvent = false
128                 };
129             } else {
130                 mSensorConfigList[(mNumSensorConfigs)++] = {
131                     .listIndex = sensorIndex,
132                     .type = atoi(argv[currArgumentIndex+1]),
133                     .rate = atoi(argv[currArgumentIndex+2]),
134                     .reportLatency = 0,
135                     .receivedEvent = false
136                 };
137             }
138 
139             currArgumentIndex += 3;
140         } else if (!strcmp(argv[currArgumentIndex], "-b")) {
141             if (currArgumentIndex + 3 >= argc) {
142                 printf ("Not enough arguments for batch option\n");
143                 return false;
144             }
145 
146             if ((sensorIndex = findSensorTypeInSensorList(atoi(argv[currArgumentIndex+1]))) < 0) {
147                 printf ("No sensor found with type \"%d\"\n", atoi(argv[currArgumentIndex+1]));
148                 return false;
149             }
150 
151             existingSensorConfigIndex = findSensorTypeInConfigList(atoi(argv[currArgumentIndex+1]));
152 
153             if (existingSensorConfigIndex >= 0) {
154                 printf("Replacing previous config for sensor type %d\n", atoi(argv[currArgumentIndex+1]));
155                 mSensorConfigList[existingSensorConfigIndex] = {
156                     .listIndex = sensorIndex,
157                     .type = atoi(argv[currArgumentIndex+1]),
158                     .rate = atoi(argv[currArgumentIndex+2]),
159                     .reportLatency = atoi(argv[currArgumentIndex+3]),
160                     .receivedEvent = false
161                 };
162             } else {
163                 mSensorConfigList[(mNumSensorConfigs)++] = {
164                     .listIndex = sensorIndex,
165                     .type = atoi(argv[currArgumentIndex+1]),
166                     .rate = atoi(argv[currArgumentIndex+2]),
167                     .reportLatency = atoi(argv[currArgumentIndex+3]),
168                     .receivedEvent = false
169                 };
170             }
171 
172             currArgumentIndex += 4;
173         } else if (!strcmp(argv[currArgumentIndex], "-c")) {
174             mContinuousMode = true;
175             currArgumentIndex++;
176         } else {
177             printf("Invalid argument \"%s\"\n", argv[currArgumentIndex]);
178             return false;
179         }
180     }
181 
182     return true;
183 }
184 
hasReceivedAllEvents()185 bool hasReceivedAllEvents()
186 {
187     for (int i = 0; i < mNumSensorConfigs; i++) {
188         if (!mSensorConfigList[i].receivedEvent) {
189             return false;
190         }
191     }
192 
193     return true;
194 };
195 
main(int argc,char ** argv)196 int main(int argc, char **argv) {
197     int numSensorEvents;
198     ASensorEvent sensorEvents[16];
199     int configListIndex;
200 
201     mSensorManager = ASensorManager_getInstanceForPackage("");
202     mNumSensors = ASensorManager_getSensorList(mSensorManager, &mSensorList);
203 
204     if ((argc == 1) || !parseArguments(argc, argv)) {
205         showHelp();
206         return -1;
207     }
208 
209     if (mNumSensorConfigs <= 0)
210         return 0;
211 
212     ALooper *mLooper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
213     ASensorEventQueue *sensorEventQueue = ASensorManager_createEventQueue(mSensorManager, mLooper, 0, NULL, NULL);
214 
215     for (int i = 0; i < mNumSensorConfigs; i++) {
216         if (ASensorEventQueue_registerSensor(sensorEventQueue, mSensorList[mSensorConfigList[i].listIndex],
217                                              mSensorConfigList[i].rate, mSensorConfigList[i].reportLatency) < 0) {
218             printf("Unable to register sensor %d with rate %d and report latency %d\n", mSensorConfigList[i].listIndex,
219                    mSensorConfigList[i].rate, mSensorConfigList[i].reportLatency);
220         }
221 
222     }
223 
224     while (mContinuousMode || !hasReceivedAllEvents()) {
225         if ((numSensorEvents = ASensorEventQueue_getEvents(sensorEventQueue, sensorEvents, 16)) < 0) {
226             printf("An error occurred while polling for events\n");
227             break;
228         } else if (numSensorEvents > 0) {
229             for (int i = 0; i < numSensorEvents; i++) {
230                 if ((configListIndex = findSensorTypeInConfigList(sensorEvents[i].type)) < 0) {
231                     printf("Received unexpected event for type %d\n", sensorEvents[i].type);
232                     break;
233                 }
234 
235                 if (mContinuousMode || !mSensorConfigList[configListIndex].receivedEvent) {
236                     printf("[%d] = %f, %f, %f @ %" PRId64 "\n", sensorEvents[i].type,
237                            sensorEvents[i].data[0], sensorEvents[i].data[1],
238                            sensorEvents[i].data[2], sensorEvents[i].timestamp);
239 
240                     mSensorConfigList[configListIndex].receivedEvent = true;
241 
242                     if (!mContinuousMode) {
243                         ASensorEventQueue_disableSensor(sensorEventQueue, mSensorList[mSensorConfigList[configListIndex].listIndex]);
244                     }
245                 }
246             }
247         }
248 
249         fflush(stdout);
250     }
251 
252     ASensorManager_destroyEventQueue(mSensorManager, sensorEventQueue);
253 
254     return 0;
255 }
256