Home | History | Annotate | Download | only in gps
      1 /*
      2  * Copyright (C) 2010 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 /* this implements a GPS hardware library for the Android emulator.
     18  * the following code should be built as a shared library that will be
     19  * placed into /system/lib/hw/gps.goldfish.so
     20  *
     21  * it will be loaded by the code in hardware/libhardware/hardware.c
     22  * which is itself called from android_location_GpsLocationProvider.cpp
     23  */
     24 
     25 
     26 #include <errno.h>
     27 #include <pthread.h>
     28 #include <fcntl.h>
     29 #include <sys/epoll.h>
     30 #include <math.h>
     31 #include <time.h>
     32 
     33 #define  LOG_TAG  "gps_qemu"
     34 #include <cutils/log.h>
     35 #include <cutils/sockets.h>
     36 #include <hardware/gps.h>
     37 #include "qemu_pipe.h"
     38 
     39 /* the name of the qemu-controlled pipe */
     40 #define  QEMU_CHANNEL_NAME  "qemud:gps"
     41 
     42 #define  GPS_DEBUG  0
     43 
     44 #if GPS_DEBUG
     45 #  define  D(...)   ALOGD(__VA_ARGS__)
     46 #else
     47 #  define  D(...)   ((void)0)
     48 #endif
     49 
     50 /*****************************************************************/
     51 /*****************************************************************/
     52 /*****                                                       *****/
     53 /*****       N M E A   T O K E N I Z E R                     *****/
     54 /*****                                                       *****/
     55 /*****************************************************************/
     56 /*****************************************************************/
     57 
     58 typedef struct {
     59     const char*  p;
     60     const char*  end;
     61 } Token;
     62 
     63 #define  MAX_NMEA_TOKENS  16
     64 
     65 typedef struct {
     66     int     count;
     67     Token   tokens[ MAX_NMEA_TOKENS ];
     68 } NmeaTokenizer;
     69 
     70 static int
     71 nmea_tokenizer_init( NmeaTokenizer*  t, const char*  p, const char*  end )
     72 {
     73     int    count = 0;
     74     char*  q;
     75 
     76     // the initial '$' is optional
     77     if (p < end && p[0] == '$')
     78         p += 1;
     79 
     80     // remove trailing newline
     81     if (end > p && end[-1] == '\n') {
     82         end -= 1;
     83         if (end > p && end[-1] == '\r')
     84             end -= 1;
     85     }
     86 
     87     // get rid of checksum at the end of the sentecne
     88     if (end >= p+3 && end[-3] == '*') {
     89         end -= 3;
     90     }
     91 
     92     while (p < end) {
     93         const char*  q = p;
     94 
     95         q = memchr(p, ',', end-p);
     96         if (q == NULL)
     97             q = end;
     98 
     99         if (count < MAX_NMEA_TOKENS) {
    100             t->tokens[count].p   = p;
    101             t->tokens[count].end = q;
    102             count += 1;
    103         }
    104         if (q < end)
    105             q += 1;
    106 
    107         p = q;
    108     }
    109 
    110     t->count = count;
    111     return count;
    112 }
    113 
    114 static Token
    115 nmea_tokenizer_get( NmeaTokenizer*  t, int  index )
    116 {
    117     Token  tok;
    118     static const char*  dummy = "";
    119 
    120     if (index < 0 || index >= t->count) {
    121         tok.p = tok.end = dummy;
    122     } else
    123         tok = t->tokens[index];
    124 
    125     return tok;
    126 }
    127 
    128 
    129 static int
    130 str2int( const char*  p, const char*  end )
    131 {
    132     int   result = 0;
    133     int   len    = end - p;
    134 
    135     for ( ; len > 0; len--, p++ )
    136     {
    137         int  c;
    138 
    139         if (p >= end)
    140             goto Fail;
    141 
    142         c = *p - '0';
    143         if ((unsigned)c >= 10)
    144             goto Fail;
    145 
    146         result = result*10 + c;
    147     }
    148     return  result;
    149 
    150 Fail:
    151     return -1;
    152 }
    153 
    154 static double
    155 str2float( const char*  p, const char*  end )
    156 {
    157     int   result = 0;
    158     int   len    = end - p;
    159     char  temp[16];
    160 
    161     if (len >= (int)sizeof(temp))
    162         return 0.;
    163 
    164     memcpy( temp, p, len );
    165     temp[len] = 0;
    166     return strtod( temp, NULL );
    167 }
    168 
    169 /*****************************************************************/
    170 /*****************************************************************/
    171 /*****                                                       *****/
    172 /*****       N M E A   P A R S E R                           *****/
    173 /*****                                                       *****/
    174 /*****************************************************************/
    175 /*****************************************************************/
    176 
    177 #define  NMEA_MAX_SIZE  83
    178 
    179 typedef struct {
    180     int     pos;
    181     int     overflow;
    182     int     utc_year;
    183     int     utc_mon;
    184     int     utc_day;
    185     int     utc_diff;
    186     GpsLocation  fix;
    187     gps_location_callback  callback;
    188     char    in[ NMEA_MAX_SIZE+1 ];
    189 } NmeaReader;
    190 
    191 
    192 static void
    193 nmea_reader_update_utc_diff( NmeaReader*  r )
    194 {
    195     time_t         now = time(NULL);
    196     struct tm      tm_local;
    197     struct tm      tm_utc;
    198     long           time_local, time_utc;
    199 
    200     gmtime_r( &now, &tm_utc );
    201     localtime_r( &now, &tm_local );
    202 
    203     time_local = tm_local.tm_sec +
    204                  60*(tm_local.tm_min +
    205                  60*(tm_local.tm_hour +
    206                  24*(tm_local.tm_yday +
    207                  365*tm_local.tm_year)));
    208 
    209     time_utc = tm_utc.tm_sec +
    210                60*(tm_utc.tm_min +
    211                60*(tm_utc.tm_hour +
    212                24*(tm_utc.tm_yday +
    213                365*tm_utc.tm_year)));
    214 
    215     r->utc_diff = time_utc - time_local;
    216 }
    217 
    218 
    219 static void
    220 nmea_reader_init( NmeaReader*  r )
    221 {
    222     memset( r, 0, sizeof(*r) );
    223 
    224     r->pos      = 0;
    225     r->overflow = 0;
    226     r->utc_year = -1;
    227     r->utc_mon  = -1;
    228     r->utc_day  = -1;
    229     r->callback = NULL;
    230     r->fix.size = sizeof(r->fix);
    231 
    232     nmea_reader_update_utc_diff( r );
    233 }
    234 
    235 
    236 static void
    237 nmea_reader_set_callback( NmeaReader*  r, gps_location_callback  cb )
    238 {
    239     r->callback = cb;
    240     if (cb != NULL && r->fix.flags != 0) {
    241         D("%s: sending latest fix to new callback", __FUNCTION__);
    242         r->callback( &r->fix );
    243     }
    244 }
    245 
    246 
    247 static int
    248 nmea_reader_update_time( NmeaReader*  r, Token  tok )
    249 {
    250     int        hour, minute;
    251     double     seconds;
    252     struct tm  tm;
    253     time_t     fix_time;
    254 
    255     if (tok.p + 6 > tok.end)
    256         return -1;
    257 
    258     if (r->utc_year < 0) {
    259         // no date yet, get current one
    260         time_t  now = time(NULL);
    261         gmtime_r( &now, &tm );
    262         r->utc_year = tm.tm_year + 1900;
    263         r->utc_mon  = tm.tm_mon + 1;
    264         r->utc_day  = tm.tm_mday;
    265     }
    266 
    267     hour    = str2int(tok.p,   tok.p+2);
    268     minute  = str2int(tok.p+2, tok.p+4);
    269     seconds = str2float(tok.p+4, tok.end);
    270 
    271     tm.tm_hour  = hour;
    272     tm.tm_min   = minute;
    273     tm.tm_sec   = (int) seconds;
    274     tm.tm_year  = r->utc_year - 1900;
    275     tm.tm_mon   = r->utc_mon - 1;
    276     tm.tm_mday  = r->utc_day;
    277     tm.tm_isdst = -1;
    278 
    279     // This is a little confusing, let's use an example:
    280     // Suppose now it's 1970-1-1 01:00 GMT, local time is 1970-1-1 00:00 GMT-1
    281     // Then the utc_diff is 3600.
    282     // The time string from GPS is 01:00:00, mktime assumes it's a local
    283     // time. So we are doing mktime for 1970-1-1 01:00 GMT-1. The result of
    284     // mktime is 7200 (1970-1-1 02:00 GMT) actually. To get the correct
    285     // timestamp, we have to subtract utc_diff here.
    286     fix_time = mktime( &tm ) - r->utc_diff;
    287     r->fix.timestamp = (long long)fix_time * 1000;
    288     return 0;
    289 }
    290 
    291 static int
    292 nmea_reader_update_date( NmeaReader*  r, Token  date, Token  time )
    293 {
    294     Token  tok = date;
    295     int    day, mon, year;
    296 
    297     if (tok.p + 6 != tok.end) {
    298         D("date not properly formatted: '%.*s'", tok.end-tok.p, tok.p);
    299         return -1;
    300     }
    301     day  = str2int(tok.p, tok.p+2);
    302     mon  = str2int(tok.p+2, tok.p+4);
    303     year = str2int(tok.p+4, tok.p+6) + 2000;
    304 
    305     if ((day|mon|year) < 0) {
    306         D("date not properly formatted: '%.*s'", tok.end-tok.p, tok.p);
    307         return -1;
    308     }
    309 
    310     r->utc_year  = year;
    311     r->utc_mon   = mon;
    312     r->utc_day   = day;
    313 
    314     return nmea_reader_update_time( r, time );
    315 }
    316 
    317 
    318 static double
    319 convert_from_hhmm( Token  tok )
    320 {
    321     double  val     = str2float(tok.p, tok.end);
    322     int     degrees = (int)(floor(val) / 100);
    323     double  minutes = val - degrees*100.;
    324     double  dcoord  = degrees + minutes / 60.0;
    325     return dcoord;
    326 }
    327 
    328 
    329 static int
    330 nmea_reader_update_latlong( NmeaReader*  r,
    331                             Token        latitude,
    332                             char         latitudeHemi,
    333                             Token        longitude,
    334                             char         longitudeHemi )
    335 {
    336     double   lat, lon;
    337     Token    tok;
    338 
    339     tok = latitude;
    340     if (tok.p + 6 > tok.end) {
    341         D("latitude is too short: '%.*s'", tok.end-tok.p, tok.p);
    342         return -1;
    343     }
    344     lat = convert_from_hhmm(tok);
    345     if (latitudeHemi == 'S')
    346         lat = -lat;
    347 
    348     tok = longitude;
    349     if (tok.p + 6 > tok.end) {
    350         D("longitude is too short: '%.*s'", tok.end-tok.p, tok.p);
    351         return -1;
    352     }
    353     lon = convert_from_hhmm(tok);
    354     if (longitudeHemi == 'W')
    355         lon = -lon;
    356 
    357     r->fix.flags    |= GPS_LOCATION_HAS_LAT_LONG;
    358     r->fix.latitude  = lat;
    359     r->fix.longitude = lon;
    360     return 0;
    361 }
    362 
    363 
    364 static int
    365 nmea_reader_update_altitude( NmeaReader* r,
    366                              Token altitude,
    367                              Token __unused units )
    368 {
    369     double  alt;
    370     Token   tok = altitude;
    371 
    372     if (tok.p >= tok.end)
    373         return -1;
    374 
    375     r->fix.flags   |= GPS_LOCATION_HAS_ALTITUDE;
    376     r->fix.altitude = str2float(tok.p, tok.end);
    377     return 0;
    378 }
    379 
    380 
    381 static int
    382 nmea_reader_update_bearing( NmeaReader*  r,
    383                             Token        bearing )
    384 {
    385     double  alt;
    386     Token   tok = bearing;
    387 
    388     if (tok.p >= tok.end)
    389         return -1;
    390 
    391     r->fix.flags   |= GPS_LOCATION_HAS_BEARING;
    392     r->fix.bearing  = str2float(tok.p, tok.end);
    393     return 0;
    394 }
    395 
    396 
    397 static int
    398 nmea_reader_update_speed( NmeaReader*  r,
    399                           Token        speed )
    400 {
    401     double  alt;
    402     Token   tok = speed;
    403 
    404     if (tok.p >= tok.end)
    405         return -1;
    406 
    407     r->fix.flags   |= GPS_LOCATION_HAS_SPEED;
    408     r->fix.speed    = str2float(tok.p, tok.end);
    409     return 0;
    410 }
    411 
    412 static int
    413 nmea_reader_update_accuracy( NmeaReader*  r )
    414 {
    415     // Always return 20m accuracy.
    416     // Possibly parse it from the NMEA sentence in the future.
    417     r->fix.flags    |= GPS_LOCATION_HAS_ACCURACY;
    418     r->fix.accuracy = 20;
    419     return 0;
    420 }
    421 
    422 
    423 static void
    424 nmea_reader_parse( NmeaReader*  r )
    425 {
    426    /* we received a complete sentence, now parse it to generate
    427     * a new GPS fix...
    428     */
    429     NmeaTokenizer  tzer[1];
    430     Token          tok;
    431 
    432     D("Received: '%.*s'", r->pos, r->in);
    433     if (r->pos < 9) {
    434         D("Too short. discarded.");
    435         return;
    436     }
    437 
    438     nmea_tokenizer_init(tzer, r->in, r->in + r->pos);
    439 #if GPS_DEBUG
    440     {
    441         int  n;
    442         D("Found %d tokens", tzer->count);
    443         for (n = 0; n < tzer->count; n++) {
    444             Token  tok = nmea_tokenizer_get(tzer,n);
    445             D("%2d: '%.*s'", n, tok.end-tok.p, tok.p);
    446         }
    447     }
    448 #endif
    449 
    450     tok = nmea_tokenizer_get(tzer, 0);
    451     if (tok.p + 5 > tok.end) {
    452         D("sentence id '%.*s' too short, ignored.", tok.end-tok.p, tok.p);
    453         return;
    454     }
    455 
    456     // ignore first two characters.
    457     tok.p += 2;
    458     if ( !memcmp(tok.p, "GGA", 3) ) {
    459         // GPS fix
    460         Token  tok_time          = nmea_tokenizer_get(tzer,1);
    461         Token  tok_latitude      = nmea_tokenizer_get(tzer,2);
    462         Token  tok_latitudeHemi  = nmea_tokenizer_get(tzer,3);
    463         Token  tok_longitude     = nmea_tokenizer_get(tzer,4);
    464         Token  tok_longitudeHemi = nmea_tokenizer_get(tzer,5);
    465         Token  tok_altitude      = nmea_tokenizer_get(tzer,9);
    466         Token  tok_altitudeUnits = nmea_tokenizer_get(tzer,10);
    467 
    468         r->fix.flags = 0;
    469         nmea_reader_update_time(r, tok_time);
    470         nmea_reader_update_latlong(r, tok_latitude,
    471                                       tok_latitudeHemi.p[0],
    472                                       tok_longitude,
    473                                       tok_longitudeHemi.p[0]);
    474         nmea_reader_update_altitude(r, tok_altitude, tok_altitudeUnits);
    475 
    476     } else if ( !memcmp(tok.p, "GSA", 3) ) {
    477         // do something ?
    478     } else if ( !memcmp(tok.p, "RMC", 3) ) {
    479         Token  tok_time          = nmea_tokenizer_get(tzer,1);
    480         Token  tok_fixStatus     = nmea_tokenizer_get(tzer,2);
    481         Token  tok_latitude      = nmea_tokenizer_get(tzer,3);
    482         Token  tok_latitudeHemi  = nmea_tokenizer_get(tzer,4);
    483         Token  tok_longitude     = nmea_tokenizer_get(tzer,5);
    484         Token  tok_longitudeHemi = nmea_tokenizer_get(tzer,6);
    485         Token  tok_speed         = nmea_tokenizer_get(tzer,7);
    486         Token  tok_bearing       = nmea_tokenizer_get(tzer,8);
    487         Token  tok_date          = nmea_tokenizer_get(tzer,9);
    488 
    489         D("in RMC, fixStatus=%c", tok_fixStatus.p[0]);
    490         if (tok_fixStatus.p[0] == 'A')
    491         {
    492             r->fix.flags = 0;
    493             nmea_reader_update_date( r, tok_date, tok_time );
    494 
    495             nmea_reader_update_latlong( r, tok_latitude,
    496                                            tok_latitudeHemi.p[0],
    497                                            tok_longitude,
    498                                            tok_longitudeHemi.p[0] );
    499 
    500             nmea_reader_update_bearing( r, tok_bearing );
    501             nmea_reader_update_speed  ( r, tok_speed );
    502         }
    503     } else {
    504         tok.p -= 2;
    505         D("unknown sentence '%.*s", tok.end-tok.p, tok.p);
    506     }
    507 
    508     // Always update accuracy
    509     nmea_reader_update_accuracy( r );
    510 
    511     if (r->fix.flags != 0) {
    512 #if GPS_DEBUG
    513         char   temp[256];
    514         char*  p   = temp;
    515         char*  end = p + sizeof(temp);
    516         struct tm   utc;
    517 
    518         p += snprintf( p, end-p, "sending fix" );
    519         if (r->fix.flags & GPS_LOCATION_HAS_LAT_LONG) {
    520             p += snprintf(p, end-p, " lat=%g lon=%g", r->fix.latitude, r->fix.longitude);
    521         }
    522         if (r->fix.flags & GPS_LOCATION_HAS_ALTITUDE) {
    523             p += snprintf(p, end-p, " altitude=%g", r->fix.altitude);
    524         }
    525         if (r->fix.flags & GPS_LOCATION_HAS_SPEED) {
    526             p += snprintf(p, end-p, " speed=%g", r->fix.speed);
    527         }
    528         if (r->fix.flags & GPS_LOCATION_HAS_BEARING) {
    529             p += snprintf(p, end-p, " bearing=%g", r->fix.bearing);
    530         }
    531         if (r->fix.flags & GPS_LOCATION_HAS_ACCURACY) {
    532             p += snprintf(p,end-p, " accuracy=%g", r->fix.accuracy);
    533         }
    534         gmtime_r( (time_t*) &r->fix.timestamp, &utc );
    535         p += snprintf(p, end-p, " time=%s", asctime( &utc ) );
    536         D(temp);
    537 #endif
    538         if (r->callback) {
    539             r->callback( &r->fix );
    540         }
    541         else {
    542             D("no callback, keeping data until needed !");
    543         }
    544     }
    545 }
    546 
    547 
    548 static void
    549 nmea_reader_addc( NmeaReader*  r, int  c )
    550 {
    551     if (r->overflow) {
    552         r->overflow = (c != '\n');
    553         return;
    554     }
    555 
    556     if (r->pos >= (int) sizeof(r->in)-1 ) {
    557         r->overflow = 1;
    558         r->pos      = 0;
    559         return;
    560     }
    561 
    562     r->in[r->pos] = (char)c;
    563     r->pos       += 1;
    564 
    565     if (c == '\n') {
    566         nmea_reader_parse( r );
    567         r->pos = 0;
    568     }
    569 }
    570 
    571 
    572 /*****************************************************************/
    573 /*****************************************************************/
    574 /*****                                                       *****/
    575 /*****       C O N N E C T I O N   S T A T E                 *****/
    576 /*****                                                       *****/
    577 /*****************************************************************/
    578 /*****************************************************************/
    579 
    580 /* commands sent to the gps thread */
    581 enum {
    582     CMD_QUIT  = 0,
    583     CMD_START = 1,
    584     CMD_STOP  = 2
    585 };
    586 
    587 
    588 /* this is the state of our connection to the qemu_gpsd daemon */
    589 typedef struct {
    590     int                     init;
    591     int                     fd;
    592     GpsCallbacks            callbacks;
    593     pthread_t               thread;
    594     int                     control[2];
    595 } GpsState;
    596 
    597 static GpsState  _gps_state[1];
    598 
    599 
    600 static void
    601 gps_state_done( GpsState*  s )
    602 {
    603     // tell the thread to quit, and wait for it
    604     char   cmd = CMD_QUIT;
    605     void*  dummy;
    606     write( s->control[0], &cmd, 1 );
    607     pthread_join(s->thread, &dummy);
    608 
    609     // close the control socket pair
    610     close( s->control[0] ); s->control[0] = -1;
    611     close( s->control[1] ); s->control[1] = -1;
    612 
    613     // close connection to the QEMU GPS daemon
    614     close( s->fd ); s->fd = -1;
    615     s->init = 0;
    616 }
    617 
    618 
    619 static void
    620 gps_state_start( GpsState*  s )
    621 {
    622     char  cmd = CMD_START;
    623     int   ret;
    624 
    625     do { ret=write( s->control[0], &cmd, 1 ); }
    626     while (ret < 0 && errno == EINTR);
    627 
    628     if (ret != 1)
    629         D("%s: could not send CMD_START command: ret=%d: %s",
    630           __FUNCTION__, ret, strerror(errno));
    631 }
    632 
    633 
    634 static void
    635 gps_state_stop( GpsState*  s )
    636 {
    637     char  cmd = CMD_STOP;
    638     int   ret;
    639 
    640     do { ret=write( s->control[0], &cmd, 1 ); }
    641     while (ret < 0 && errno == EINTR);
    642 
    643     if (ret != 1)
    644         D("%s: could not send CMD_STOP command: ret=%d: %s",
    645           __FUNCTION__, ret, strerror(errno));
    646 }
    647 
    648 
    649 static int
    650 epoll_register( int  epoll_fd, int  fd )
    651 {
    652     struct epoll_event  ev;
    653     int                 ret, flags;
    654 
    655     /* important: make the fd non-blocking */
    656     flags = fcntl(fd, F_GETFL);
    657     fcntl(fd, F_SETFL, flags | O_NONBLOCK);
    658 
    659     ev.events  = EPOLLIN;
    660     ev.data.fd = fd;
    661     do {
    662         ret = epoll_ctl( epoll_fd, EPOLL_CTL_ADD, fd, &ev );
    663     } while (ret < 0 && errno == EINTR);
    664     return ret;
    665 }
    666 
    667 
    668 static int
    669 epoll_deregister( int  epoll_fd, int  fd )
    670 {
    671     int  ret;
    672     do {
    673         ret = epoll_ctl( epoll_fd, EPOLL_CTL_DEL, fd, NULL );
    674     } while (ret < 0 && errno == EINTR);
    675     return ret;
    676 }
    677 
    678 /* this is the main thread, it waits for commands from gps_state_start/stop and,
    679  * when started, messages from the QEMU GPS daemon. these are simple NMEA sentences
    680  * that must be parsed to be converted into GPS fixes sent to the framework
    681  */
    682 static void
    683 gps_state_thread( void*  arg )
    684 {
    685     GpsState*   state = (GpsState*) arg;
    686     NmeaReader  reader[1];
    687     int         epoll_fd   = epoll_create(2);
    688     int         started    = 0;
    689     int         gps_fd     = state->fd;
    690     int         control_fd = state->control[1];
    691     GpsStatus gps_status;
    692     gps_status.size = sizeof(gps_status);
    693     GpsSvStatus  gps_sv_status;
    694     memset(&gps_sv_status, 0, sizeof(gps_sv_status));
    695     gps_sv_status.size = sizeof(gps_sv_status);
    696     gps_sv_status.num_svs = 1;
    697     gps_sv_status.sv_list[0].size = sizeof(gps_sv_status.sv_list[0]);
    698     gps_sv_status.sv_list[0].prn = 17;
    699     gps_sv_status.sv_list[0].snr = 60.0;
    700     gps_sv_status.sv_list[0].elevation = 30.0;
    701     gps_sv_status.sv_list[0].azimuth = 30.0;
    702 
    703     nmea_reader_init( reader );
    704 
    705     // register control file descriptors for polling
    706     epoll_register( epoll_fd, control_fd );
    707     epoll_register( epoll_fd, gps_fd );
    708 
    709     D("gps thread running");
    710 
    711     // now loop
    712     for (;;) {
    713         struct epoll_event   events[2];
    714         int                  ne, nevents;
    715 
    716         int timeout = -1;
    717         if (gps_status.status == GPS_STATUS_SESSION_BEGIN) {
    718             timeout = 10 * 1000; // 10 seconds
    719         }
    720         nevents = epoll_wait( epoll_fd, events, 2, timeout );
    721         if (state->callbacks.sv_status_cb) {
    722             state->callbacks.sv_status_cb(&gps_sv_status);
    723         }
    724         // update satilite info
    725         if (nevents < 0) {
    726             if (errno != EINTR)
    727                 ALOGE("epoll_wait() unexpected error: %s", strerror(errno));
    728             continue;
    729         }
    730         D("gps thread received %d events", nevents);
    731         for (ne = 0; ne < nevents; ne++) {
    732             if ((events[ne].events & (EPOLLERR|EPOLLHUP)) != 0) {
    733                 ALOGE("EPOLLERR or EPOLLHUP after epoll_wait() !?");
    734                 return;
    735             }
    736             if ((events[ne].events & EPOLLIN) != 0) {
    737                 int  fd = events[ne].data.fd;
    738 
    739                 if (fd == control_fd)
    740                 {
    741                     char  cmd = 255;
    742                     int   ret;
    743                     D("gps control fd event");
    744                     do {
    745                         ret = read( fd, &cmd, 1 );
    746                     } while (ret < 0 && errno == EINTR);
    747 
    748                     if (cmd == CMD_QUIT) {
    749                         D("gps thread quitting on demand");
    750                         return;
    751                     }
    752                     else if (cmd == CMD_START) {
    753                         if (!started) {
    754                             D("gps thread starting  location_cb=%p", state->callbacks.location_cb);
    755                             started = 1;
    756                             nmea_reader_set_callback( reader, state->callbacks.location_cb );
    757                             gps_status.status = GPS_STATUS_SESSION_BEGIN;
    758                             if (state->callbacks.status_cb) {
    759                                 state->callbacks.status_cb(&gps_status);
    760                             }
    761                         }
    762                     }
    763                     else if (cmd == CMD_STOP) {
    764                         if (started) {
    765                             D("gps thread stopping");
    766                             started = 0;
    767                             nmea_reader_set_callback( reader, NULL );
    768                             gps_status.status = GPS_STATUS_SESSION_END;
    769                             if (state->callbacks.status_cb) {
    770                                 state->callbacks.status_cb(&gps_status);
    771                             }
    772                         }
    773                     }
    774                 }
    775                 else if (fd == gps_fd)
    776                 {
    777                     char  buff[32];
    778                     D("gps fd event");
    779                     for (;;) {
    780                         int  nn, ret;
    781 
    782                         ret = read( fd, buff, sizeof(buff) );
    783                         if (ret < 0) {
    784                             if (errno == EINTR)
    785                                 continue;
    786                             if (errno != EWOULDBLOCK)
    787                                 ALOGE("error while reading from gps daemon socket: %s:", strerror(errno));
    788                             break;
    789                         }
    790                         D("received %d bytes: %.*s", ret, ret, buff);
    791                         for (nn = 0; nn < ret; nn++)
    792                             nmea_reader_addc( reader, buff[nn] );
    793                     }
    794                     D("gps fd event end");
    795                 }
    796                 else
    797                 {
    798                     ALOGE("epoll_wait() returned unkown fd %d ?", fd);
    799                 }
    800             }
    801         }
    802     }
    803 }
    804 
    805 
    806 static void
    807 gps_state_init( GpsState*  state, GpsCallbacks* callbacks )
    808 {
    809     state->init       = 1;
    810     state->control[0] = -1;
    811     state->control[1] = -1;
    812     state->fd         = -1;
    813 
    814     state->fd = qemu_pipe_open(QEMU_CHANNEL_NAME);
    815 
    816     if (state->fd < 0) {
    817         D("no gps emulation detected");
    818         return;
    819     }
    820 
    821     D("gps emulation will read from '%s' qemu pipe", QEMU_CHANNEL_NAME );
    822 
    823     if ( socketpair( AF_LOCAL, SOCK_STREAM, 0, state->control ) < 0 ) {
    824         ALOGE("could not create thread control socket pair: %s", strerror(errno));
    825         goto Fail;
    826     }
    827 
    828     state->thread = callbacks->create_thread_cb( "gps_state_thread", gps_state_thread, state );
    829 
    830     if ( !state->thread ) {
    831         ALOGE("could not create gps thread: %s", strerror(errno));
    832         goto Fail;
    833     }
    834 
    835     state->callbacks = *callbacks;
    836 
    837     // Explicitly initialize capabilities
    838     state->callbacks.set_capabilities_cb(0);
    839 
    840 
    841     // Setup system info, we are pre 2016 hardware.
    842     GnssSystemInfo sysinfo;
    843     sysinfo.size = sizeof(GnssSystemInfo);
    844     sysinfo.year_of_hw = 2015;
    845     state->callbacks.set_system_info_cb(&sysinfo);
    846 
    847     D("gps state initialized");
    848     return;
    849 
    850 Fail:
    851     gps_state_done( state );
    852 }
    853 
    854 
    855 /*****************************************************************/
    856 /*****************************************************************/
    857 /*****                                                       *****/
    858 /*****       I N T E R F A C E                               *****/
    859 /*****                                                       *****/
    860 /*****************************************************************/
    861 /*****************************************************************/
    862 
    863 
    864 static int
    865 qemu_gps_init(GpsCallbacks* callbacks)
    866 {
    867     GpsState*  s = _gps_state;
    868 
    869     if (!s->init)
    870         gps_state_init(s, callbacks);
    871 
    872     if (s->fd < 0)
    873         return -1;
    874 
    875     return 0;
    876 }
    877 
    878 static void
    879 qemu_gps_cleanup(void)
    880 {
    881     GpsState*  s = _gps_state;
    882 
    883     if (s->init)
    884         gps_state_done(s);
    885 }
    886 
    887 
    888 static int
    889 qemu_gps_start()
    890 {
    891     GpsState*  s = _gps_state;
    892 
    893     if (!s->init) {
    894         D("%s: called with uninitialized state !!", __FUNCTION__);
    895         return -1;
    896     }
    897 
    898     D("%s: called", __FUNCTION__);
    899     gps_state_start(s);
    900     return 0;
    901 }
    902 
    903 
    904 static int
    905 qemu_gps_stop()
    906 {
    907     GpsState*  s = _gps_state;
    908 
    909     if (!s->init) {
    910         D("%s: called with uninitialized state !!", __FUNCTION__);
    911         return -1;
    912     }
    913 
    914     D("%s: called", __FUNCTION__);
    915     gps_state_stop(s);
    916     return 0;
    917 }
    918 
    919 
    920 static int
    921 qemu_gps_inject_time(GpsUtcTime __unused time,
    922                      int64_t __unused timeReference,
    923                      int __unused uncertainty)
    924 {
    925     return 0;
    926 }
    927 
    928 static int
    929 qemu_gps_inject_location(double __unused latitude,
    930                          double __unused longitude,
    931                          float __unused accuracy)
    932 {
    933     return 0;
    934 }
    935 
    936 static void
    937 qemu_gps_delete_aiding_data(GpsAidingData __unused flags)
    938 {
    939 }
    940 
    941 static int qemu_gps_set_position_mode(GpsPositionMode __unused mode,
    942                                       GpsPositionRecurrence __unused recurrence,
    943                                       uint32_t __unused min_interval,
    944                                       uint32_t __unused preferred_accuracy,
    945                                       uint32_t __unused preferred_time)
    946 {
    947     // FIXME - support fix_frequency
    948     return 0;
    949 }
    950 
    951 static const void*
    952 qemu_gps_get_extension(const char* __unused name)
    953 {
    954     // no extensions supported
    955     return NULL;
    956 }
    957 
    958 static const GpsInterface  qemuGpsInterface = {
    959     sizeof(GpsInterface),
    960     qemu_gps_init,
    961     qemu_gps_start,
    962     qemu_gps_stop,
    963     qemu_gps_cleanup,
    964     qemu_gps_inject_time,
    965     qemu_gps_inject_location,
    966     qemu_gps_delete_aiding_data,
    967     qemu_gps_set_position_mode,
    968     qemu_gps_get_extension,
    969 };
    970 
    971 const GpsInterface* gps__get_gps_interface(struct gps_device_t* __unused dev)
    972 {
    973     return &qemuGpsInterface;
    974 }
    975 
    976 static int open_gps(const struct hw_module_t* module,
    977                     char const* __unused name,
    978                     struct hw_device_t** device)
    979 {
    980     struct gps_device_t *dev = malloc(sizeof(struct gps_device_t));
    981     memset(dev, 0, sizeof(*dev));
    982 
    983     dev->common.tag = HARDWARE_DEVICE_TAG;
    984     dev->common.version = 0;
    985     dev->common.module = (struct hw_module_t*)module;
    986 //    dev->common.close = (int (*)(struct hw_device_t*))close_lights;
    987     dev->get_gps_interface = gps__get_gps_interface;
    988 
    989     *device = (struct hw_device_t*)dev;
    990     return 0;
    991 }
    992 
    993 
    994 static struct hw_module_methods_t gps_module_methods = {
    995     .open = open_gps
    996 };
    997 
    998 struct hw_module_t HAL_MODULE_INFO_SYM = {
    999     .tag = HARDWARE_MODULE_TAG,
   1000     .version_major = 1,
   1001     .version_minor = 0,
   1002     .id = GPS_HARDWARE_MODULE_ID,
   1003     .name = "Goldfish GPS Module",
   1004     .author = "The Android Open Source Project",
   1005     .methods = &gps_module_methods,
   1006 };
   1007