Imported Upstream version 0.1.0+git20131207+e452e83
[deb_libhybris.git] / hybris / tests / test_gps.c
1 /*
2 * Copyright (C) 2012 Jolla Ltd.
3 * Author: Philippe De Swert <philippe.deswert@jollamobile.com>
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19 #include <pthread.h>
20 #include <signal.h>
21 #include <stdio.h>
22 #include <unistd.h>
23 #include <stdlib.h>
24 #include <sys/time.h>
25 #include <getopt.h>
26 #include <string.h>
27
28 #include <android/hardware/gps.h>
29
30 const GpsInterface* Gps = NULL;
31 const AGpsInterface* AGps = NULL;
32 const AGpsRilInterface* AGpsRil = NULL;
33 const GpsNiInterface *GpsNi = NULL;
34 const GpsXtraInterface *GpsExtra = NULL;
35 #ifdef HAVE_ULP
36 const UlpNetworkInterface *UlpNetwork = NULL;
37 const UlpPhoneContextInterface *UlpPhoneContext = NULL;
38 #endif /* HAVE_ULP */
39 char *apn = 0;
40
41 static const GpsInterface* get_gps_interface()
42 {
43 int error;
44 hw_module_t* module;
45 const GpsInterface* interface = NULL;
46 struct gps_device_t *device;
47
48 error = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
49
50 if (!error)
51 {
52 error = module->methods->open(module, GPS_HARDWARE_MODULE_ID, (struct hw_device_t **) &device);
53 fprintf(stdout, "*** device info\n id = %s\n name = %s\n author = %s\n",
54 module->id, module->name, module->author);
55
56 if (!error)
57 {
58 interface = device->get_gps_interface(device);
59 }
60 }
61 else
62 {
63 fprintf(stdout, "*** GPS interface not found :\(\n Bye! \n");
64 exit(1);
65 }
66
67 return interface;
68 }
69
70 static const AGpsInterface* get_agps_interface(const GpsInterface *gps)
71 {
72 const AGpsInterface* interface = NULL;
73
74 if (gps)
75 {
76 interface = (const AGpsInterface*)gps->get_extension(AGPS_INTERFACE);
77 }
78 return interface;
79 }
80
81 static const AGpsRilInterface* get_agps_ril_interface(const GpsInterface *gps)
82 {
83 const AGpsRilInterface* interface = NULL;
84
85 if (gps)
86 {
87 interface = (const AGpsRilInterface*)gps->get_extension(AGPS_RIL_INTERFACE);
88 }
89 return interface;
90 }
91
92 static const GpsNiInterface* get_gps_ni_interface(const GpsInterface *gps)
93 {
94 const GpsNiInterface* interface = NULL;
95
96 if(gps)
97 {
98 interface = (const GpsNiInterface*)gps->get_extension(GPS_NI_INTERFACE);
99 }
100 return interface;
101 }
102
103 static const GpsDebugInterface* get_gps_debug_interface(const GpsInterface *gps)
104 {
105 const GpsDebugInterface* interface = NULL;
106
107 if(gps)
108 {
109 interface = (const GpsDebugInterface*)gps->get_extension(GPS_DEBUG_INTERFACE);
110 }
111 return interface;
112 }
113
114 static const GpsXtraInterface* get_gps_extra_interface(const GpsInterface *gps)
115 {
116 const GpsXtraInterface* interface = NULL;
117
118 if(gps)
119 {
120 interface = (const GpsXtraInterface*)gps->get_extension(GPS_XTRA_INTERFACE);
121 }
122 return interface;
123 }
124
125 #ifdef HAVE_ULP
126 static const UlpNetworkInterface* get_ulp_network_interface(const GpsInterface *gps)
127 {
128 const UlpNetworkInterface* interface = NULL;
129
130 if (gps)
131 {
132 interface = (const UlpNetworkInterface*)gps->get_extension(ULP_NETWORK_INTERFACE);
133 }
134 return interface;
135 }
136
137 static const UlpPhoneContextInterface* get_ulp_phone_context_interface(const GpsInterface *gps)
138 {
139 const UlpPhoneContextInterface* interface = NULL;
140
141 if (gps)
142 {
143 interface = (const UlpPhoneContextInterface*)gps->get_extension(ULP_PHONE_CONTEXT_INTERFACE);
144 }
145 return interface;
146 }
147 #endif /* HAVE_ULP */
148
149 static void location_callback(GpsLocation* location)
150 {
151 fprintf(stdout, "*** location callback\n");
152 fprintf(stdout, "flags:\t%d\n", location->flags);
153 fprintf(stdout, "latitude: \t%lf\n", location->latitude);
154 fprintf(stdout, "longtide: \t%lf\n", location->longitude);
155 fprintf(stdout, "accuracy:\t%f\n", location->accuracy);
156 fprintf(stdout, "utc: \t%ld\n", (long)location->timestamp);
157 }
158
159 static void status_callback(GpsStatus* status)
160 {
161 fprintf(stdout, "*** status callback\n");
162
163 switch (status->status)
164 {
165 case GPS_STATUS_NONE:
166 fprintf(stdout, "*** no gps\n");
167 break;
168 case GPS_STATUS_SESSION_BEGIN:
169 fprintf(stdout, "*** session begin\n");
170 break;
171 case GPS_STATUS_SESSION_END:
172 fprintf(stdout, "*** session end\n");
173 break;
174 case GPS_STATUS_ENGINE_ON:
175 fprintf(stdout, "*** engine on\n");
176 break;
177 case GPS_STATUS_ENGINE_OFF:
178 fprintf(stdout, "*** engine off\n");
179 break;
180 default:
181 fprintf(stdout, "*** unknown status\n");
182 }
183 }
184
185 static void sv_status_callback(GpsSvStatus* sv_info)
186 {
187 int i = 0;
188
189 fprintf(stdout, "*** sv status\n");
190 fprintf(stdout, "sv_size:\t%zu\n", sv_info->size);
191 fprintf(stdout, "num_svs:\t%d\n", sv_info->num_svs);
192 for(i=0; i < sv_info->num_svs; i++)
193 {
194 fprintf(stdout, "\t azimuth:\t%f\n", sv_info->sv_list[i].azimuth);
195 fprintf(stdout, "\t elevation:\t%f\n", sv_info->sv_list[i].elevation);
196 /* if prn > 65 and <= 88 this is a glonass sattelite */
197 fprintf(stdout, "\t prn:\t%d\n", sv_info->sv_list[i].prn);
198 fprintf(stdout, "\t size:\t%zu\n", sv_info->sv_list[i].size);
199 fprintf(stdout, "\t snr:\t%f\n", sv_info->sv_list[i].snr);
200 }
201
202 }
203
204 static void nmea_callback(GpsUtcTime timestamp, const char* nmea, int length)
205 {
206 char buf[83];
207 fprintf(stdout, "*** nmea info\n");
208 fprintf(stdout, "timestamp:\t%ld\n", (long)timestamp);
209 /* NMEA sentences can only be between 11 ($TTFFF*CC\r\n) and 82 characters long */
210 if (length > 10 && length < 83) {
211 strncpy(buf, nmea, length);
212 buf[length] = '\0';
213 fprintf(stdout, "nmea (%d): \t%s\n", length, buf);
214 } else {
215 fprintf(stdout, "Invalid nmea data\n");
216 }
217 }
218
219 static void set_capabilities_callback(uint32_t capabilities)
220 {
221 fprintf(stdout, "*** set capabilities\n");
222 fprintf(stdout, "capability is %.8x\n", capabilities);
223 /* do nothing */
224 }
225
226 static void acquire_wakelock_callback()
227 {
228 fprintf(stdout, "*** acquire wakelock\n");
229 /* do nothing */
230 }
231
232 static void release_wakelock_callback()
233 {
234 fprintf(stdout, "*** release wakelock\n");
235 /* do nothing */
236 }
237
238 struct ThreadWrapperContext {
239 void (*func)(void *);
240 void *user_data;
241 };
242
243 static void *thread_wrapper_context_main_func(void *user_data)
244 {
245 struct ThreadWrapperContext *ctx = (struct ThreadWrapperContext *)user_data;
246
247 fprintf(stderr, " **** Thread wrapper start (start=%p, arg=%p) ****\n",
248 ctx->func, ctx->user_data);
249 ctx->func(ctx->user_data);
250 fprintf(stderr, " **** Thread wrapper end (start=%p, arg=%p) ****\n",
251 ctx->func, ctx->user_data);
252
253 free(ctx);
254
255 return NULL;
256 }
257
258 static pthread_t create_thread_callback(const char* name, void (*start)(void *), void* arg)
259 {
260 pthread_t thread_id;
261 int error = 0;
262
263 /* Wrap thread function, so we can return void * to pthread and log start/end of thread */
264 struct ThreadWrapperContext *ctx = calloc(1, sizeof(struct ThreadWrapperContext));
265 ctx->func = start;
266 ctx->user_data = arg;
267
268 fprintf(stderr, " ** Creating thread: '%s' (start=%p, arg=%p)\n", name, start, arg);
269 /* Do not use a pthread_attr_t (we'd have to take care of bionic/glibc differences) */
270 error = pthread_create(&thread_id, NULL, thread_wrapper_context_main_func, ctx);
271 fprintf(stderr, " ** After thread_create: '%s', error=%d (start=%p, arg=%p)\n", name, error, start, arg);
272
273 if(error != 0)
274 return 0;
275
276 return thread_id;
277 }
278
279 static void agps_handle_status_callback(AGpsStatus *status)
280 {
281 if(status->type)
282 {
283 fprintf(stdout, "*** gps type %d\n", status->type);
284 }
285 switch (status->status)
286 {
287 case GPS_REQUEST_AGPS_DATA_CONN:
288 fprintf(stdout, "*** data_conn_open\n");
289 #ifndef HAS_ANDROID_4_2_0
290 AGps->data_conn_open(AGPS_TYPE_SUPL, apn, AGPS_APN_BEARER_IPV4);
291 #else
292 AGps->data_conn_open(apn);
293 #endif
294 break;
295 case GPS_RELEASE_AGPS_DATA_CONN:
296 fprintf(stdout, "*** data_conn_closed\n");
297 #ifndef HAS_ANDROID_4_2_0
298 AGps->data_conn_closed(AGPS_TYPE_SUPL);
299 #else
300 AGps->data_conn_closed();
301 #endif
302 break;
303 case GPS_AGPS_DATA_CONNECTED:
304 fprintf(stdout, "*** data_conn_established\n");
305 break;
306 case GPS_AGPS_DATA_CONN_DONE:
307 fprintf(stdout, "*** data_conn_done\n");
308 break;
309 case GPS_AGPS_DATA_CONN_FAILED:
310 fprintf(stdout, "*** data_conn_FAILED\n");
311 break;
312 }
313 }
314
315 static void agps_ril_set_id_callback(uint32_t flags)
316 {
317 fprintf(stdout, "*** set_id_cb\n");
318 AGpsRil->set_set_id(AGPS_SETID_TYPE_IMSI, "000000000000000");
319 }
320
321 static void agps_ril_refloc_callback(uint32_t flags)
322 {
323 fprintf(stdout, "*** refloc_cb\n");
324 /* TODO : find out how to fill in location
325 AGpsRefLocation location;
326 AGpsRil->set_ref_location(&location, sizeof(location));
327 */
328 }
329
330 static void ni_notify_callback (GpsNiNotification *notification)
331 {
332 fprintf(stdout, "*** ni notification callback\n");
333 }
334
335 static void download_xtra_request_callback (void)
336 {
337 fprintf(stdout, "*** xtra download request to client\n");
338 }
339
340 #ifdef HAVE_ULP
341 static void ulp_network_location_request_callback(UlpNetworkRequestPos *req)
342 {
343 fprintf(stdout, "*** ulp network location request (request_type=%#x, interval_ms=%d, desired_position_source=%#x)\n",
344 req->request_type, req->interval_ms, req->desired_position_source);
345 }
346
347 static void ulp_request_phone_context_callback(UlpPhoneContextRequest *req)
348 {
349 fprintf(stdout, "*** ulp phone context request (context_type=%#x, request_type=%#x, interval_ms=%d)\n",
350 req->context_type, req->request_type, req->interval_ms);
351
352 if (UlpPhoneContext) {
353 fprintf(stdout, "*** sending ulp phone context reply\n");
354 UlpPhoneContextSettings settings;
355 settings.context_type = req->context_type;
356 settings.is_gps_enabled = 1;
357 settings.is_agps_enabled = 1;
358 settings.is_network_position_available = 1;
359 settings.is_wifi_setting_enabled = 1;
360 settings.is_battery_charging = 0;
361 settings.is_enh_location_services_enabled = 1;
362 UlpPhoneContext->ulp_phone_context_settings_update(&settings);
363 }
364 }
365 #endif /* HAVE_ULP */
366
367 GpsCallbacks callbacks = {
368 sizeof(GpsCallbacks),
369 location_callback,
370 status_callback,
371 sv_status_callback,
372 nmea_callback,
373 set_capabilities_callback,
374 acquire_wakelock_callback,
375 release_wakelock_callback,
376 create_thread_callback,
377 };
378
379 AGpsCallbacks callbacks2 = {
380 agps_handle_status_callback,
381 create_thread_callback,
382 };
383
384 AGpsRilCallbacks callbacks3 = {
385 agps_ril_set_id_callback,
386 agps_ril_refloc_callback,
387 create_thread_callback,
388 };
389
390 GpsNiCallbacks callbacks4 = {
391 ni_notify_callback,
392 create_thread_callback,
393 };
394
395 GpsXtraCallbacks callbacks5 = {
396 download_xtra_request_callback,
397 create_thread_callback,
398 };
399
400 #ifdef HAVE_ULP
401 UlpNetworkLocationCallbacks callbacks6 = {
402 ulp_network_location_request_callback,
403 };
404
405 UlpPhoneContextCallbacks callbacks7 = {
406 ulp_request_phone_context_callback,
407 };
408 #endif /* HAVE_ULP */
409
410 void sigint_handler(int signum)
411 {
412 fprintf(stdout, "*** cleanup\n");
413 if(AGps)
414 {
415 #ifndef HAS_ANDROID_4_2_0
416 AGps->data_conn_closed(AGPS_TYPE_SUPL);
417 #else
418 AGps->data_conn_closed();
419 #endif
420 }
421 if (Gps)
422 {
423 Gps->stop();
424 Gps->cleanup();
425 }
426 exit (0);
427 }
428
429 int main(int argc, char *argv[])
430 {
431 int sleeptime = 6000, opt, initok = 0;
432 int coldstart = 0, extra = 0, ulp = 0;
433 struct timeval tv;
434 int agps = 0, agpsril = 0, injecttime = 0, injectlocation = 0;
435 char *location = 0, *longitude, *latitude;
436 float accuracy = 100; /* Use 100m as location accuracy by default */
437
438 while ((opt = getopt(argc, argv, "acl:p:rtux")) != -1)
439 {
440 switch (opt) {
441 case 'a':
442 agps = 1;
443 fprintf(stdout, "*** Using agps\n");
444 break;
445 case 'c':
446 coldstart = 1;
447 fprintf(stdout, "*** Using cold start\n");
448 break;
449 case 'l':
450 injectlocation = 1;
451 location = optarg;
452 fprintf(stdout, "*** Location info %s will be injected\n", location);
453 break;
454 case 'r':
455 agpsril = 1;
456 fprintf(stdout, "*** Using agpsril\n");
457 break;
458 case 't':
459 injecttime = 1;
460 fprintf(stdout, "*** Timing info will be injected\n");
461 break;
462 case 'p':
463 apn = optarg;
464 break;
465 case 'u':
466 ulp = 1;
467 break;
468 case 'x':
469 extra = 1;
470 fprintf(stdout, "*** Allowing for Xtra downloads\n");
471 break;
472 default:
473 fprintf(stderr, "\n Usage: %s \n \
474 \t-a for agps,\n \
475 \t-c for coldstarting the gps,\n \
476 \t-p <apn name> to specify an apn name,\n \
477 \t-r for agpsril,\n \
478 \t-t to inject time,\n \
479 \t-u to use ULP (if available,\n \
480 \t-x deal with Xtra gps data.\n \
481 \tnone for standalone gps\n",
482 argv[0]);
483 exit(1);
484 }
485 }
486
487 if(!apn)
488 {
489 apn = strdup("Internet");
490 }
491
492 fprintf(stdout, "*** setup signal handler\n");
493 signal(SIGINT, sigint_handler);
494
495 fprintf(stdout, "*** get gps interface\n");
496 Gps = get_gps_interface();
497
498 fprintf(stdout, "*** init gps interface\n");
499 initok = Gps->init(&callbacks);
500 fprintf(stdout, "*** setting positioning mode\n");
501 /* need to be done before starting gps or no info will come out */
502 if((agps||agpsril) && !initok)
503 Gps->set_position_mode(GPS_POSITION_MODE_MS_BASED, GPS_POSITION_RECURRENCE_PERIODIC, 1000, 0, 0);
504 else
505 Gps->set_position_mode(GPS_POSITION_MODE_STANDALONE, GPS_POSITION_RECURRENCE_PERIODIC, 1000, 0, 0);
506
507 if (Gps && !initok && (agps||agpsril))
508 {
509 fprintf(stdout, "*** get agps interface\n");
510 AGps = get_agps_interface(Gps);
511 if (AGps)
512 {
513 fprintf(stdout, "*** set up agps interface\n");
514 AGps->init(&callbacks2);
515 fprintf(stdout, "*** set up agps server\n");
516 AGps->set_server(AGPS_TYPE_SUPL, "supl.google.com", 7276);
517 }
518
519 if(agpsril)
520 {
521 fprintf(stdout, "*** get agps ril interface\n");
522
523 AGpsRil = get_agps_ril_interface(Gps);
524 if (AGpsRil)
525 {
526 AGpsRil->init(&callbacks3);
527 }
528 }
529 /* if coldstart is requested, delete all location info */
530 if(coldstart)
531 {
532 fprintf(stdout, "*** delete aiding data\n");
533 Gps->delete_aiding_data(GPS_DELETE_ALL);
534 }
535
536 if(extra)
537 {
538 fprintf(stdout, "*** xtra aiding data init\n");
539 GpsExtra = get_gps_extra_interface(Gps);
540 if(GpsExtra)
541 GpsExtra->init(&callbacks5);
542 }
543
544 fprintf(stdout, "*** setting up network notification handling\n");
545 GpsNi = get_gps_ni_interface(Gps);
546 if(GpsNi)
547 {
548 GpsNi->init(&callbacks4);
549 }
550
551 #ifdef HAVE_ULP
552 if(ulp)
553 {
554 UlpNetwork = get_ulp_network_interface(Gps);
555 if (UlpNetwork) {
556 fprintf(stdout, "*** got ulp network interface\n");
557 if (UlpNetwork->init(&callbacks6) != 0) {
558 fprintf(stdout, "*** FAILED to init ulp network interface\n");
559 UlpNetwork = NULL;
560 }
561 }
562 else
563 fprintf(stdout, "*** ULP failed!\n");
564
565 UlpPhoneContext = get_ulp_phone_context_interface(Gps);
566 if (UlpPhoneContext) {
567 fprintf(stdout, "*** got ulp phone context interface\n");
568 UlpPhoneContext->init(&callbacks7);
569 }
570 }
571 #endif /* HAVE_ULP */
572 }
573 if(injecttime)
574 {
575 fprintf(stdout, "*** aiding gps by injecting time information\n");
576 gettimeofday(&tv, NULL);
577 Gps->inject_time(tv.tv_sec, tv.tv_sec, 0);
578 }
579
580 if(injectlocation)
581 {
582 fprintf(stdout, "*** aiding gps by injecting location information\n");
583 //Gps->inject_location(double latitude, double longitude, float accuracy);
584 latitude = strtok(location, ",");
585 longitude = strtok(NULL, ",");
586 Gps->inject_location(strtod(latitude, NULL), strtod(longitude, NULL), accuracy);
587 }
588
589 fprintf(stdout, "*** start gps track\n");
590 Gps->start();
591
592 fprintf(stdout, "*** gps tracking started\n");
593
594 while(sleeptime > 0)
595 {
596 fprintf(stdout, "*** tracking.... \n");
597 sleep(100);
598 sleeptime = sleeptime - 100;
599 }
600
601 if (AGps)
602 AGps->data_conn_closed(AGPS_TYPE_SUPL);
603 fprintf(stdout, "*** stop tracking\n");
604 Gps->stop();
605 fprintf(stdout, "*** cleaning up\n");
606 Gps->cleanup();
607
608 return 0;
609 }