网上下载的代码,自己编辑修改,加入了北斗定位功能,主要是修改了GSV,GSA语句的解析,在A10平台上测试良好:
北斗双模下的LOG:
- $GPGSV,3,3,10,31,46,012,,32,39,287,40*79
- $BDGSV,1,1,04,02,45,242,43,03,00,000,34,06,00,000,32,09,38,216,37*6C
- $GNRMC,040059.080,A,2230.8804,N,11354.9920,E,0.83,0.00,040613,,,A*7C
- $GNVTG,0.00,T,,M,0.83,N,1.54,K,A*28
- $GNZDA,040059.080,04,06,2013,00,00*4A
- $GNGGA,040100.000,2230.8897,N,11355.0128,E,1,06,28.3,79.2,M,0.0,M,,*71
- $GNGLL,2230.8897,N,11355.0128,E,040100.000,A,0*36
- $GPGSA,A,3,16,20,06,32,,,,,,,,,30.4,28.3,11.2*0C
- $BDGSA,A,3,02,09,,,,,,,,,,,30.4,28.3,11.2*14
- $GPGSV,3,1,10,03,06,197,,06,19,182,33,14,50,109,,16,48,230,46*75
- $GPGSV,3,2,10,20,16,305,41,22,15,171,,29,23,066,22,30,00,000,25*72
- $GPGSV,3,3,10,31,46,012,,32,39,287,40*79
- $BDGSV,1,1,04,02,45,242,43,03,00,000,34,06,00,000,32,09,38,216,37*6C
- $GNRMC,040100.000,A,2230.8897,N,11355.0128,E,0.64,0.00,040613,,,A*72
- $GNVTG,0.00,T,,M,0.64,N,1.19,K,A*28
- $GNZDA,040100.000,04,06,2013,00,00*4F
一些命令的解释:
$GNRMC,091356.000,V,2230.8777,N,11354.9659,E,7.88,270.95,040613,,,N*63
|
这里V变成A时候表示定位成功
$GPGSV,3,1,11,01,46,169,,03,29,038,,06,13,045,,07,55,322,*74
$GPGSV,3,2,11,08,24,325,,11,72,159,,13,32,226,,16,17,081,*77
$GPGSV,3,3,11,19,49,022,,23,20,200,,28,07,296,*4D
$BDGSV,1,1,04,02,44,240,,07,64,173,,08,60,343,,10,77,244,*61
GPGSV表示GPS的GSV,BDGSV表示北斗的GSV
第一列3表示有3行GPGSV语句输出;紧接着第二列的1、2、3表示当前是第几行GSV;接着的11表示一共11颗星,接着的是4个数字为一组的信号值
$GPGSA,A,3,16,20,06,32,,,,,,,,,30.4,28.3,11.2*0C
$BDGSA,A,3,02,09,,,,,,,,,,,30.4,28.3,11.2*14
这里第3~14位,一共12位表示已经定位的卫星号,它们和GSV中可见卫星信息组中的卫星号一致,上层要判断这两个数值一致才表示可用卫星,可见
GSV中得到的是可见卫星数量,GSA中得到的是可用卫星数量,可见卫星数量>=可用卫星数量,他们就是GPS测试软件中的in view和in use数值
北斗的一些发送命令:
char *str_B115200 = "$PCAS01,5*19\r\n";
char *str_B9600 = "$PCAS01,1*1D\r\n";
char *str_save = "$PCAS00*01\r\n";//将当前配置写入flash,否则断电后恢复为默认的
char *str_beidou = "$PCAS04,2*1B\r\n"; //北斗模式
char *str_shuangmo = "$PCAS04,3*1A\r\n"; //北斗和GPS共存模式
这里的*后面的数字是异或校验,如$PCAS01,5*19这一行,'P' ^ 'C' ^ 'A' ^ 'S'^ '0' ^ '1' ^ ',' ^ '5' == 0x19;
详细的命令参考厂商的手册
下面是源代码:
Android.mk
- LOCAL_PATH := $(call my-dir)
-
- #ifneq ($(TARGET_PRODUCT),sim)
- # HAL module implemenation, not prelinked and stored in
- # hw/<GPS_HARDWARE_MODULE_ID>.<ro.hardware>.so
- include $(CLEAR_VARS)
- LOCAL_PRELINK_MODULE := false
- LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
- LOCAL_CFLAGS += -DQEMU_HARDWARE
- LOCAL_SHARED_LIBRARIES := liblog libcutils libhardware
- LOCAL_SRC_FILES := gps.c
- LOCAL_MODULE := gps.default
- LOCAL_MODULE_TAGS := optional
- include $(BUILD_SHARED_LIBRARY)
- #endif
gps.c:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- #include <errno.h>
- #include <pthread.h>
- #include <fcntl.h>
- #include <sys/epoll.h>
- #include <math.h>
- #include <time.h>
-
- #include <stdio.h> /*????????*/
-
- #include <stdlib.h> /*???????*/
-
- #include <unistd.h> /*Unix ??????*/
-
- #include <sys/types.h>
-
- #include <sys/stat.h>
-
-
- #include <termios.h> /*PPSIX ??????*/
-
- #include <errno.h> /*?????*/
-
-
-
- #define LOG_TAG "gps_qemu"
- #include <cutils/log.h>
- #include <cutils/sockets.h>
- #include <hardware/gps.h>
- #include <hardware/qemud.h>
- #include <hardware/hardware.h>
-
- #define QEMU_CHANNEL_NAME "gps"
-
- #define GPS_DEBUG 0
- #define Ublox_6M 1
- #if GPS_DEBUG
- # define D(...) LOGE(__VA_ARGS__)
- #else
- # define D(...) ((void)0)
- #endif
-
-
-
-
-
-
-
-
-
- typedef struct {
- const char* p;
- const char* end;
- } Token;
-
- #define MAX_NMEA_TOKENS 20
-
- typedef struct {
- int count;
- Token tokens[ MAX_NMEA_TOKENS ];
- } NmeaTokenizer;
-
-
- GpsStatus g_status;
-
- static int
- nmea_tokenizer_init( NmeaTokenizer* t, const char* p, const char* end )
- {
- int count = 0;
- char* q;
-
-
- if (p < end && p[0] == '$')
- p += 1;
-
-
- if (end > p && end[-1] == '\n') {
- end -= 1;
- if (end > p && end[-1] == '\r')
- end -= 1;
- }
-
-
- if (end >= p+3 && end[-3] == '*') {
- end -= 3;
- }
-
- while (p < end) {
- const char* q = p;
-
- q = memchr(p, ',', end-p);
- if (q == NULL)
- q = end;
-
- if (q >= p) {
- if (count < MAX_NMEA_TOKENS) {
- t->tokens[count].p = p;
- t->tokens[count].end = q;
- count += 1;
- }
- }
- if (q < end)
- q += 1;
-
- p = q;
- }
-
- t->count = count;
- return count;
- }
-
- static Token
- nmea_tokenizer_get( NmeaTokenizer* t, int index )
- {
- Token tok;
- static const char* dummy = "";
-
- if (index < 0 || index >= t->count) {
- tok.p = tok.end = dummy;
- } else
- tok = t->tokens[index];
-
- return tok;
- }
-
-
- static int
- str2int( const char* p, const char* end )
- {
- int result = 0;
- int len = end - p;
-
- for ( ; len > 0; len--, p++ )
- {
- int c;
-
- if (p >= end)
- goto Fail;
-
- c = *p - '0';
- if ((unsigned)c >= 10)
- goto Fail;
-
- result = result*10 + c;
- }
- return result;
-
- Fail:
- return -1;
- }
-
- static double
- str2float( const char* p, const char* end )
- {
- int result = 0;
- int len = end - p;
- char temp[16];
-
- if (len >= (int)sizeof(temp))
- return 0.;
-
- memcpy( temp, p, len );
- temp[len] = 0;
- return strtod( temp, NULL );
- }
-
-
-
-
-
-
-
-
-
- #define NMEA_MAX_SIZE 83
-
- typedef struct {
- int pos;
- int overflow;
- int utc_year;
- int utc_mon;
- int utc_day;
- int utc_diff;
- GpsLocation fix;
-
- GpsSvStatus sv_status;
-
- int sv_status_changed;
- #ifdef Ublox_6M
- GpsCallbacks callback;
-
- #else
-
- gps_location_callback callback;
- #endif
- char in[ NMEA_MAX_SIZE+1 ];
- } NmeaReader;
-
-
- static void
- nmea_reader_update_utc_diff( NmeaReader* r )
- {
- time_t now = time(NULL);
- struct tm tm_local;
- struct tm tm_utc;
- long time_local, time_utc;
-
- gmtime_r( &now, &tm_utc );
- localtime_r( &now, &tm_local );
-
- time_local = tm_local.tm_sec +
- 60*(tm_local.tm_min +
- 60*(tm_local.tm_hour +
- 24*(tm_local.tm_yday +
- 365*tm_local.tm_year)));
-
- time_utc = tm_utc.tm_sec +
- 60*(tm_utc.tm_min +
- 60*(tm_utc.tm_hour +
- 24*(tm_utc.tm_yday +
- 365*tm_utc.tm_year)));
-
- r->utc_diff = time_local - time_utc;
- }
-
-
- static void
- nmea_reader_init( NmeaReader* r )
- {
- memset( r, 0, sizeof(*r) );
-
- r->pos = 0;
- r->overflow = 0;
- r->utc_year = -1;
- r->utc_mon = -1;
- r->utc_day = -1;
- #ifdef Ublox_6M
- r->callback.sv_status_cb = NULL;
- r->callback.nmea_cb = NULL;
- r->callback.location_cb = NULL;
- r->callback.status_cb = NULL;
- #else
- r->callback = NULL;
- #endif
- r->fix.size = sizeof(r->fix);
- nmea_reader_update_utc_diff( r );
- }
-
-
- static void
- nmea_reader_set_callback( NmeaReader* r, gps_location_callback cb )
- {
- #ifdef Ublox_6M
- r->callback.location_cb = cb;
- #else
- r->callback = cb;
- #endif
- if (cb != NULL && r->fix.flags != 0) {
- D("%s: sending latest fix to new callback", __FUNCTION__);
- #ifdef Ublox_6M
- r->callback.location_cb( &r->fix );
- #else
- r->fix.flags = 0;
- #endif
- }
- }
-
-
- static int
- nmea_reader_update_time( NmeaReader* r, Token tok )
- {
- int hour, minute;
- double seconds;
- struct tm tm;
- time_t fix_time;
-
- if (tok.p + 6 > tok.end)
- return -1;
-
- if (r->utc_year < 0) {
-
- time_t now = time(NULL);
- gmtime_r( &now, &tm );
- r->utc_year = tm.tm_year + 1900;
- r->utc_mon = tm.tm_mon + 1;
- r->utc_day = tm.tm_mday;
- }
-
- hour = str2int(tok.p, tok.p+2);
- minute = str2int(tok.p+2, tok.p+4);
- seconds = str2float(tok.p+4, tok.end);
-
- tm.tm_hour = hour;
- tm.tm_min = minute;
- tm.tm_sec = (int) seconds;
- tm.tm_year = r->utc_year - 1900;
- tm.tm_mon = r->utc_mon - 1;
- tm.tm_mday = r->utc_day;
- tm.tm_isdst = -1;
-
- fix_time = mktime( &tm ) + r->utc_diff;
- r->fix.timestamp = (long long)fix_time * 1000;
- return 0;
- }
-
- static int
- nmea_reader_update_date( NmeaReader* r, Token date, Token time )
- {
- Token tok = date;
- int day, mon, year;
-
- if (tok.p + 6 != tok.end) {
- D("date not properly formatted: '%.*s'", tok.end-tok.p, tok.p);
- return -1;
- }
- day = str2int(tok.p, tok.p+2);
- mon = str2int(tok.p+2, tok.p+4);
- year = str2int(tok.p+4, tok.p+6) + 2000;
-
- if ((day|mon|year) < 0) {
- D("date not properly formatted: '%.*s'", tok.end-tok.p, tok.p);
- return -1;
- }
-
- r->utc_year = year;
- r->utc_mon = mon;
- r->utc_day = day;
-
- return nmea_reader_update_time( r, time );
- }
-
-
- static double
- convert_from_hhmm( Token tok )
- {
- double val = str2float(tok.p, tok.end);
- int degrees = (int)(floor(val) / 100);
- double minutes = val - degrees*100.;
- double dcoord = degrees + minutes / 60.0;
- return dcoord;
- }
-
-
- static int
- nmea_reader_update_latlong( NmeaReader* r,
- Token latitude,
- char latitudeHemi,
- Token longitude,
- char longitudeHemi )
- {
- double lat, lon;
- Token tok;
-
- tok = latitude;
- if (tok.p + 6 > tok.end) {
- D("latitude is too short: '%.*s'", tok.end-tok.p, tok.p);
- return -1;
- }
- lat = convert_from_hhmm(tok);
- if (latitudeHemi == 'S')
- lat = -lat;
-
- tok = longitude;
- if (tok.p + 6 > tok.end) {
- D("longitude is too short: '%.*s'", tok.end-tok.p, tok.p);
- return -1;
- }
- lon = convert_from_hhmm(tok);
- if (longitudeHemi == 'W')
- lon = -lon;
-
- r->fix.flags |= GPS_LOCATION_HAS_LAT_LONG;
- r->fix.latitude = lat;
- r->fix.longitude = lon;
- return 0;
- }
-
-
- static int
- nmea_reader_update_altitude( NmeaReader* r,
- Token altitude,
- Token units )
- {
- double alt;
- Token tok = altitude;
-
- if (tok.p >= tok.end)
- return -1;
-
- r->fix.flags |= GPS_LOCATION_HAS_ALTITUDE;
- r->fix.altitude = str2float(tok.p, tok.end);
- return 0;
- }
-
-
- static int
- nmea_reader_update_bearing( NmeaReader* r,
- Token bearing )
- {
- double alt;
- Token tok = bearing;
-
- if (tok.p >= tok.end)
- return -1;
-
- r->fix.flags |= GPS_LOCATION_HAS_BEARING;
- r->fix.bearing = str2float(tok.p, tok.end);
- return 0;
- }
-
-
- static int
- nmea_reader_update_speed( NmeaReader* r,
- Token speed )
- {
- double alt;
- Token tok = speed;
-
- if (tok.p >= tok.end)
- return -1;
-
- r->fix.flags |= GPS_LOCATION_HAS_SPEED;
- r->fix.speed = str2float(tok.p, tok.end);
- return 0;
- }
- static int nmea_reader_update_accuracy(NmeaReader * r, Token accuracy)
- {
- double acc;
- Token tok = accuracy;
-
- if(tok.p >= tok.end)
- return -1;
-
- r->fix.accuracy = str2float(tok.p, tok.end);
-
- if(r->fix.accuracy == 99.99){
- return 0;
- }
-
- r->fix.flags |= GPS_LOCATION_HAS_ACCURACY;
- return 0;
- }
-
- /* this is the state of our connection to the qemu_gpsd daemon */
- typedef struct {
- int init;
- int fd;
- GpsCallbacks callbacks;
- pthread_t thread;
- int control[2];
- } GpsState;
-
- static GpsState _gps_state[1];
-
- static void
- nmea_reader_parse( NmeaReader* r )
- {
-
-
-
- NmeaTokenizer tzer[1];
- Token tok;
- char *ptr;
-
- D("Received: '%.*s'", r->pos, r->in);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- if (r->pos < 9) {
- D("Too short. discarded.");
- return;
- }
-
- nmea_tokenizer_init(tzer, r->in, r->in + r->pos);
- #if GPS_DEBUG
- {
- int n;
- D("Found %d tokens", tzer->count);
- for (n = 0; n < tzer->count; n++) {
- Token tok = nmea_tokenizer_get(tzer,n);
- D("%2d: '%.*s'", n, tok.end-tok.p, tok.p);
- }
- }
- #endif
-
- tok = nmea_tokenizer_get(tzer, 0);
- if (tok.p + 5 > tok.end) {
- D("sentence id '%.*s' too short, ignored.", tok.end-tok.p, tok.p);
- return;
- }
-
-
- ptr = tok.p;
- tok.p += 2;
- if ( !memcmp(tok.p, "GGA", 3) ) {
-
- Token tok_time = nmea_tokenizer_get(tzer,1);
- Token tok_latitude = nmea_tokenizer_get(tzer,2);
- Token tok_latitudeHemi = nmea_tokenizer_get(tzer,3);
- Token tok_longitude = nmea_tokenizer_get(tzer,4);
- Token tok_longitudeHemi = nmea_tokenizer_get(tzer,5);
- Token tok_altitude = nmea_tokenizer_get(tzer,9);
- Token tok_altitudeUnits = nmea_tokenizer_get(tzer,10);
-
- nmea_reader_update_time(r, tok_time);
- nmea_reader_update_latlong(r, tok_latitude,
- tok_latitudeHemi.p[0],
- tok_longitude,
- tok_longitudeHemi.p[0]);
- nmea_reader_update_altitude(r, tok_altitude, tok_altitudeUnits);
-
- } else if ( !memcmp(tok.p, "GSA", 3) ) {
-
- int is_beidou = !memcmp(ptr, "BD", 2);
-
- #ifdef Ublox_6M
-
- {
- D("may%s,%d,%s,gsa\n",__FILE__,__LINE__,__FUNCTION__);
- Token tok_fixStatus = nmea_tokenizer_get(tzer, 2);
- int i;
-
- if (tok_fixStatus.p[0] != '\0' && tok_fixStatus.p[0] != '1') {
-
- Token tok_accuracy = nmea_tokenizer_get(tzer, 15);
-
- nmea_reader_update_accuracy(r, tok_accuracy);
-
- if(!is_beidou)
- r->sv_status.used_in_fix_mask = 0ul;
- D("\n");
- for (i = 3; i <= 14; ++i){
-
- Token tok_prn = nmea_tokenizer_get(tzer, i);
- int prn = str2int(tok_prn.p, tok_prn.end);
- D("gsa,prn=%d,",prn);
- if (prn > 0){
- r->sv_status.used_in_fix_mask |= (1ul << ( prn-1));
-
-
- r->sv_status_changed = 1;
-
- }
-
- }D("\n");
- D("%s: fix mask is %x", __FUNCTION__, r->sv_status.used_in_fix_mask);
-
- }
-
- D(" [log hit][%s:%d] fix.flags=0x%x ", __FUNCTION__, __LINE__, r->fix.flags);
-
- }
- #endif
-
-
-
- }
- #ifdef Ublox_6M
- else if ( !memcmp(tok.p, "GSV", 3) ) {
- int is_beidou = !memcmp(ptr, "BD", 2);
- D("sclu is_Beidou = %d", is_beidou);
-
- D("may%s,%d,%s,gsV\n",__FILE__,__LINE__,__FUNCTION__);
- Token tok_noSatellites = nmea_tokenizer_get(tzer, 3);
- int noSatellites = str2int(tok_noSatellites.p, tok_noSatellites.end);
- D("%d,inview=%d,\n",__LINE__,noSatellites);
- if (noSatellites > 0) {
- Token tok_noSentences = nmea_tokenizer_get(tzer, 1);
- Token tok_sentence = nmea_tokenizer_get(tzer, 2);
-
- int sentence = str2int(tok_sentence.p, tok_sentence.end);
- int totalSentences = str2int(tok_noSentences.p, tok_noSentences.end);
- D("%d,gsv_index=%d,gsv_total=%d\n",__LINE__,sentence,totalSentences);
- int curr;
- int i;
-
- if ((sentence == 1) && !is_beidou) {
- D("msg_index=%d\n",sentence);
-
- r->sv_status.num_svs = 0;
- r->sv_status.ephemeris_mask=0ul;
- r->sv_status.almanac_mask=0ul;
- }
-
- curr = r->sv_status.num_svs;
-
- i = 0;
-
- if(is_beidou && (sentence == 1)){
- noSatellites += r->sv_status.num_svs;
- D("sclu add beidou total num");
- }
-
- while (i < 4 && r->sv_status.num_svs < noSatellites){
- Token tok_prn = nmea_tokenizer_get(tzer, i * 4 + 4);
- Token tok_elevation = nmea_tokenizer_get(tzer, i * 4 + 5);
- Token tok_azimuth = nmea_tokenizer_get(tzer, i * 4 + 6);
- Token tok_snr = nmea_tokenizer_get(tzer, i * 4 + 7);
-
- r->sv_status.sv_list[curr].prn = str2int(tok_prn.p, tok_prn.end);
- if(is_beidou){
- D("sclu, number = %d", r->sv_status.sv_list[curr].prn);
-
- }
- r->sv_status.sv_list[curr].elevation = str2float(tok_elevation.p, tok_elevation.end);
- r->sv_status.sv_list[curr].azimuth = str2float(tok_azimuth.p, tok_azimuth.end);
- r->sv_status.sv_list[curr].snr = str2float(tok_snr.p, tok_snr.end);
- r->sv_status.ephemeris_mask|=(1ul << (r->sv_status.sv_list[curr].prn-1));
- r->sv_status.almanac_mask|=(1ul << (r->sv_status.sv_list[curr].prn-1));
- r->sv_status.num_svs += 1;
- D("**********curr=%d\n",curr);
-
- D("%d,prn=%d:snr=%f\n",__LINE__,r->sv_status.sv_list[curr].prn,r->sv_status.sv_list[curr].snr);
- curr += 1;
-
- i += 1;
- }
-
- if ((sentence == totalSentences) && is_beidou) {
- D("msg=%d,msgindex=%d, curr=%d",totalSentences,sentence, curr);
- #ifdef Ublox_6M
- r->callback.sv_status_cb=_gps_state->callbacks.sv_status_cb;
-
- if (r->sv_status_changed !=0) {
- if (r->callback.sv_status_cb) {
-
- #if GPS_DEBUG
- D("%d,SV_STATSU,change=%d\n",__LINE__,r->sv_status_changed);
- int nums=r->sv_status.num_svs;
- D("num_svs=%d,emask=%x,amask=%x,inusemask=%x\n",r->sv_status.num_svs,r->sv_status.ephemeris_mask,r->sv_status.almanac_mask,r->sv_status.used_in_fix_mask);
- D("************88\n");
- while(nums)
- {
- nums--;
- D("prn=%d:snr=%f\n",r->sv_status.sv_list[nums].prn,r->sv_status.sv_list[nums].snr);
-
- }D("************88\n");
- #endif
- r->callback.sv_status_cb( &(r->sv_status) );
- r->sv_status_changed = 0;
- }else {
- D("no callback, keeping status data until needed !");
- }
-
- }
- #endif
- }
-
- D("%s: GSV message with total satellites %d", __FUNCTION__, noSatellites);
-
- }
-
- }
- #endif////////////////////////////////////////////////////////////////////////////////////////////
-
- else if ( !memcmp(tok.p, "GLL", 3) ) {
- Token tok_fixstaus = nmea_tokenizer_get(tzer,6);
- if (tok_fixstaus.p[0] == 'A') {
- Token tok_latitude = nmea_tokenizer_get(tzer,1);
- Token tok_latitudeHemi = nmea_tokenizer_get(tzer,2);
- Token tok_longitude = nmea_tokenizer_get(tzer,3);
- Token tok_longitudeHemi = nmea_tokenizer_get(tzer,4);
- Token tok_time = nmea_tokenizer_get(tzer,5);
- nmea_reader_update_time(r, tok_time);
- nmea_reader_update_latlong(r, tok_latitude, tok_latitudeHemi.p[0], tok_longitude, tok_longitudeHemi.p[0]);
- }
- }
-
-
-
- else if ( !memcmp(tok.p, "RMC", 3) ) {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Token tok_time = nmea_tokenizer_get(tzer,1);
- Token tok_fixStatus = nmea_tokenizer_get(tzer,2);
- Token tok_latitude = nmea_tokenizer_get(tzer,3);
- Token tok_latitudeHemi = nmea_tokenizer_get(tzer,4);
- Token tok_longitude = nmea_tokenizer_get(tzer,5);
- Token tok_longitudeHemi = nmea_tokenizer_get(tzer,6);
- Token tok_speed = nmea_tokenizer_get(tzer,7);
- Token tok_bearing = nmea_tokenizer_get(tzer,8);
- Token tok_date = nmea_tokenizer_get(tzer,9);
-
- D("in RMC, fixStatus=%c", tok_fixStatus.p[0]);
- if (tok_fixStatus.p[0] == 'A')
- {
- nmea_reader_update_date( r, tok_date, tok_time );
-
- nmea_reader_update_latlong( r, tok_latitude,
- tok_latitudeHemi.p[0],
- tok_longitude,
- tok_longitudeHemi.p[0] );
-
- nmea_reader_update_bearing( r, tok_bearing );
- nmea_reader_update_speed ( r, tok_speed );
- #ifdef Ublox_6M
- r->callback.location_cb=_gps_state->callbacks.location_cb;
- r->callback.nmea_cb=_gps_state->callbacks.nmea_cb;
- r->callback.status_cb=_gps_state->callbacks.status_cb;
- if (r->callback.status_cb) {
- D("report,status,flags=%d\n",r->fix.flags);
- r->callback.status_cb( (struct GpsStatus *)&(r->fix.flags) );
- }
- if (r->callback.location_cb) {
- D("location_cb report:r->fix.flags=%d,r->latitude=%f,r->longitude=%f,r->altitude=%f,r->speed=%f,r->bearing=%f,r->accuracy=%f\n",r->fix.flags,r->fix.latitude,r->fix.longitude,r->fix.altitude,r->fix.speed,r->fix.bearing,r->fix.accuracy);
- r->callback.location_cb( &r->fix );
- r->fix.flags = 0;
-
- }
- if (r->callback.nmea_cb) {
- D("report,timestamp=%llx,%llu\n",r->fix.timestamp,r->fix.timestamp);
- r->callback.nmea_cb( r->fix.timestamp,r->in,r->pos );
-
-
- }
-
- #else
- r->callback=_gps_state.callbacks->location_cb;
-
- if (r->callback) {D("if2 (r->callback.location_cb)\n");
- r->callback( &r->fix );
- r->fix.flags = 0;
- }
- #endif
- }
-
- }
-
- else
- {
- tok.p -= 2;
- D("unknown sentence '%.*s", tok.end-tok.p, tok.p);
- }
- if (r->fix.flags != 0) {
- #if GPS_DEBUG
- char temp[256];
- char* p = temp;
- char* end = p + sizeof(temp);
- struct tm utc;
-
- p += snprintf( p, end-p, "sending fix" );
- if (r->fix.flags & GPS_LOCATION_HAS_LAT_LONG) {
- p += snprintf(p, end-p, " lat=%g lon=%g", r->fix.latitude, r->fix.longitude);
- }
- if (r->fix.flags & GPS_LOCATION_HAS_ALTITUDE) {
- p += snprintf(p, end-p, " altitude=%g", r->fix.altitude);
- }
- if (r->fix.flags & GPS_LOCATION_HAS_SPEED) {
- p += snprintf(p, end-p, " speed=%g", r->fix.speed);
- }
- if (r->fix.flags & GPS_LOCATION_HAS_BEARING) {
- p += snprintf(p, end-p, " bearing=%g", r->fix.bearing);
- }
- if (r->fix.flags & GPS_LOCATION_HAS_ACCURACY) {
- p += snprintf(p,end-p, " accuracy=%g", r->fix.accuracy);
- }
- gmtime_r( (time_t*) &r->fix.timestamp, &utc );
- p += snprintf(p, end-p, " time=%s", asctime( &utc ) );
- LOGD("%s",temp);
- #endif
-
-
-
-
-
-
-
- }
- }
-
-
- static void
- nmea_reader_addc( NmeaReader* r, int c )
- {
- if (r->overflow) {
- r->overflow = (c != '\n');
- return;
- }
-
- if (r->pos >= (int) sizeof(r->in)-1 ) {
- r->overflow = 1;
- r->pos = 0;
- return;
- }
-
- r->in[r->pos] = (char)c;
- r->pos += 1;
-
- if (c == '\n') {
- nmea_reader_parse( r );
- r->pos = 0;
- }
- }
-
-
-
-
-
-
-
-
-
-
-
- enum {
- CMD_QUIT = 0,
- CMD_START = 1,
- CMD_STOP = 2
- };
-
-
-
-
- static void
- gps_state_done( GpsState* s )
- {
-
- char cmd = CMD_QUIT;
- void* dummy;
- write( s->control[0], &cmd, 1 );
- pthread_join(s->thread, &dummy);
-
-
- close( s->control[0] ); s->control[0] = -1;
- close( s->control[1] ); s->control[1] = -1;
-
-
- close( s->fd ); s->fd = -1;
- s->init = 0;
- }
-
-
- static void
- gps_state_start( GpsState* s )
- {
- char cmd = CMD_START;
- int ret;
-
- do { ret=write( s->control[0], &cmd, 1 ); }
- while (ret < 0 && errno == EINTR);
-
- if (ret != 1)
- D("%s: could not send CMD_START command: ret=%d: %s",
- __FUNCTION__, ret, strerror(errno));
- }
-
-
- static void
- gps_state_stop( GpsState* s )
- {
- char cmd = CMD_STOP;
- int ret;
-
- do { ret=write( s->control[0], &cmd, 1 ); }
- while (ret < 0 && errno == EINTR);
-
- if (ret != 1)
- D("%s: could not send CMD_STOP command: ret=%d: %s",
- __FUNCTION__, ret, strerror(errno));
- }
-
-
- static int
- epoll_register( int epoll_fd, int fd )
- {
- struct epoll_event ev;
- int ret, flags;
-
-
- flags = fcntl(fd, F_GETFL);
- fcntl(fd, F_SETFL, flags | O_NONBLOCK);
-
- ev.events = EPOLLIN;
- ev.data.fd = fd;
- do {
- ret = epoll_ctl( epoll_fd, EPOLL_CTL_ADD, fd, &ev );
- } while (ret < 0 && errno == EINTR);
- return ret;
- }
-
-
- static int
- epoll_deregister( int epoll_fd, int fd )
- {
- int ret;
- do {
- ret = epoll_ctl( epoll_fd, EPOLL_CTL_DEL, fd, NULL );
- } while (ret < 0 && errno == EINTR);
- return ret;
- }
-
-
-
-
-
- static void
- gps_state_thread( void* arg )
- {
- GpsState* state = (GpsState*) arg;
- NmeaReader reader[1];
- int epoll_fd = epoll_create(2);
- int started = 0;
- int gps_fd = state->fd;
- int control_fd = state->control[1];
-
- nmea_reader_init( reader );
-
-
- epoll_register( epoll_fd, control_fd );
- epoll_register( epoll_fd, gps_fd );
-
- D("gps thread running");
-
-
- for (;;) {
- struct epoll_event events[2];
- int ne, nevents;
-
- nevents = epoll_wait( epoll_fd, events, 2, -1 );
- if (nevents < 0) {
- if (errno != EINTR)
- LOGE("epoll_wait() unexpected error: %s", strerror(errno));
- continue;
- }
- D("gps thread received %d events", nevents);
- for (ne = 0; ne < nevents; ne++) {
- if ((events[ne].events & (EPOLLERR|EPOLLHUP)) != 0) {
- LOGE("EPOLLERR or EPOLLHUP after epoll_wait() !?");
- goto Exit;
- }
- if ((events[ne].events & EPOLLIN) != 0) {
- int fd = events[ne].data.fd;
-
- if (fd == control_fd)
- {
- char cmd = 255;
- int ret;
- D("gps control fd event");
- do {
- ret = read( fd, &cmd, 1 );
- } while (ret < 0 && errno == EINTR);
-
- if (cmd == CMD_QUIT) {
- D("gps thread quitting on demand");
- goto Exit;
- }
- else if (cmd == CMD_START) {
- if (!started) {
- D("gps thread starting location_cb=%p", state->callbacks.location_cb);
- started = 1;
-
- g_status.status=GPS_STATUS_SESSION_BEGIN;
- state->callbacks.status_cb(&g_status);
-
- nmea_reader_set_callback( reader, state->callbacks.location_cb );
- LOGE("%d",gps_fd);
- }
- }
- else if (cmd == CMD_STOP) {
- if (started) {
- D("gps thread stopping");
- started = 0;
-
- g_status.status=GPS_STATUS_SESSION_END;
- state->callbacks.status_cb(&g_status);
-
- nmea_reader_set_callback( reader, NULL );
- }
- }
- }
- else if (fd == gps_fd)
- {
- char buff[32];
- D("gps fd event");
- for (;;) {
- int nn, ret;
-
- ret = read( fd, buff, sizeof(buff) );
- if (ret < 0) {
- if (errno == EINTR)
- continue;
- if (errno != EWOULDBLOCK)
- LOGE("error while reading from gps daemon socket: %s:", strerror(errno));
- break;
- }
- D("received %d bytes: %.*s", ret, ret, buff);
- for (nn = 0; nn < ret; nn++)
- nmea_reader_addc( reader, buff[nn] );
- }
- D("gps fd event end");
- }
- else
- {
- LOGE("epoll_wait() returned unkown fd %d ?", fd);
- }
- }
- }
- }
- Exit:
- return ;
- }
-
-
- static void
- gps_state_init( GpsState* state )
- {
- state->init = 1;
- state->control[0] = -1;
- state->control[1] = -1;
- state->fd = -1;
- int ret = -1;
- struct termios gps_termios;
-
-
- state->fd= open("/dev/ttyS3",O_RDWR|O_NOCTTY|O_NDELAY);
-
- if( state->fd < 0){
-
- LOGE("open port /dev/ttyS3 ERROR..state->fd=%s\n",strerror(state->fd));
-
- exit(0);
-
- }else
-
- LOGE("open port:/dev/ttyS3 succceed..state->fd=%d\n",state->fd);
-
- if(fcntl( state->fd,F_SETFL,0)<0)
-
- LOGE("fcntl F_SETFL\n");
-
- {
-
- LOGI(">>>> Port setup..\n");
-
- int err;
-
- tcflush(state->fd, TCIOFLUSH);
-
- if ((err = tcgetattr(state->fd,&gps_termios)) != 0)
-
- {
-
- LOGI("tcgetattr(%d) = %d,errno %d\r\n",state->fd,err,errno);
-
- close(state->fd);
-
- }
-
- gps_termios.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
-
- gps_termios.c_oflag &= ~OPOST;
-
- gps_termios.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
-
- gps_termios.c_cflag &= ~(CSIZE|PARENB);
-
- gps_termios.c_cflag |= CS8;
-
- gps_termios.c_cflag &= ~CRTSCTS;
-
-
-
- tcsetattr(state->fd, TCSANOW, &gps_termios);
-
- tcflush(state->fd, TCIOFLUSH);
-
- tcsetattr(state->fd, TCSANOW, &gps_termios);
-
- tcflush(state->fd, TCIOFLUSH);
-
- tcflush(state->fd, TCIOFLUSH);
-
-
-
- if (cfsetispeed(&gps_termios,B115200))
- {
-
- LOGE("cfsetispeed.. errno..\r\n");
-
- close(state->fd);
-
- }
-
-
-
- if (cfsetospeed(&gps_termios,B115200))
- {
- LOGE("cfsetispeed.. errno..\r\n");
-
- close(state->fd);
-
-
- }
- tcsetattr(state->fd,TCSANOW,&gps_termios);
-
- LOGE("Port setup finished..\n");
-
- }
-
- if (state->fd < 0) {
-
-
-
- LOGD("no gps emulation detected");
-
- return;
-
- }
-
-
-
-
- if ( socketpair( AF_LOCAL, SOCK_STREAM, 0, state->control ) < 0 ) {
- LOGE("could not create thread control socket pair: %s", strerror(errno));
- goto Fail;
- }
-
- /* if ( pthread_create( &state->thread, NULL, gps_state_thread, state ) != 0 ) {
- LOGE("could not create gps thread: %s", strerror(errno));
- goto Fail;
- }*/
-
- LOGE("gps state initialized before");
- state->thread=state->callbacks.create_thread_cb("gps_state_thread",gps_state_thread,state);
-
-
- LOGE("gps state initialized");
- return;
-
- Fail:
- gps_state_done( state );
- }
-
-
- /*****************************************************************/
-
-
-
-
-
-
-
-
- static int
- qemu_gps_init(GpsCallbacks* callbacks)
- {
- system("echo 1 > /sys/devices/platform/gps_power/bcm_gps_power_state");
- GpsState* s = _gps_state;
- D("%s", __FUNCTION__);
-
-
-
- s->callbacks = *callbacks;
-
- g_status.status=GPS_STATUS_ENGINE_ON;
-
- s->callbacks.status_cb(&g_status);
-
-
-
- if (!s->init)
- gps_state_init(s);
-
- if (s->fd < 0)
- return -1;
-
-
-
- return 0;
- }
-
- static void
- qemu_gps_cleanup(void)
- {
- GpsState* s = _gps_state;
-
- D("%s", __FUNCTION__);
- if (s->init)
- gps_state_done(s);
- system("echo 0 > /sys/devices/platform/gps_power/bcm_gps_power_state");
- }
-
-
- static int
- qemu_gps_start()
- {
- GpsState* s = _gps_state;
-
- D("%s", __FUNCTION__);
- if (!s->init) {
- D("%s: called with uninitialized state !!", __FUNCTION__);
- return -1;
- }
-
- gps_state_start(s);
- return 0;
- }
-
-
- static int
- qemu_gps_stop()
- {
- GpsState* s = _gps_state;
-
- D("%s", __FUNCTION__);
- if (!s->init) {
- D("%s: called with uninitialized state !!", __FUNCTION__);
- return -1;
- }
-
- D("%s: called", __FUNCTION__);
- gps_state_stop(s);
- return 0;
- }
-
-
- static int
- qemu_gps_inject_time(GpsUtcTime time, int64_t timeReference, int uncertainty)
- {
- return 0;
- }
-
- static int
- qemu_gps_inject_location(double latitude, double longitude, float accuracy)
- {
- return 0;
- }
-
- static void
- qemu_gps_delete_aiding_data(GpsAidingData flags)
- {
- }
-
- static int qemu_gps_set_position_mode(GpsPositionMode mode, GpsPositionRecurrence recurrence,uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time)
- {
-
- return 0;
- }
-
- static const void*
- qemu_gps_get_extension(const char* name)
- {
-
- return NULL;
- }
-
- static const GpsInterface qemuGpsInterface = {
- sizeof(GpsInterface),
- qemu_gps_init,
- qemu_gps_start,
- qemu_gps_stop,
- qemu_gps_cleanup,
- qemu_gps_inject_time,
- qemu_gps_inject_location,
- qemu_gps_delete_aiding_data,
- qemu_gps_set_position_mode,
- qemu_gps_get_extension,
- };
-
- const GpsInterface* gps__get_gps_interface(struct gps_device_t* dev)
- {
- return &qemuGpsInterface;
- }
-
- static int open_gps(const struct hw_module_t* module, char const* name,
- struct hw_device_t** device)
- {
- struct gps_device_t *dev = malloc(sizeof(struct gps_device_t));
- memset(dev, 0, sizeof(*dev));
-
- dev->common.tag = HARDWARE_DEVICE_TAG;
- dev->common.version = 0;
- dev->common.module = (struct hw_module_t*)module;
-
- dev->get_gps_interface = gps__get_gps_interface;
-
- *device = (struct hw_device_t*)dev;
- return 0;
- }
-
-
- static struct hw_module_methods_t gps_module_methods = {
- .open = open_gps
- };
-
- const struct hw_module_t HAL_MODULE_INFO_SYM = {
- .tag = HARDWARE_MODULE_TAG,
- .version_major = 1,
- .version_minor = 0,
- .id = GPS_HARDWARE_MODULE_ID,
- .name = "Goldfish GPS Module",
- .author = "The Android Open Source Project",
- .methods = &gps_module_methods,
- };
下面简单分析GPS源代码的上报过程,流程图如下所示:
应用:
- lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
- lm.addGpsStatusListener(statuslistener);
- private GpsStatus.Listener statuslistener = new GpsStatus.Listener(){
-
- public void onGpsStatusChanged(int event){
-
- }
- };
调用LocationManager.java:
- 1331 GpsStatusListenerTransport transport = new GpsStatusListenerTransport(listener);
- 1332 result = mService.addGpsStatusListener(transport);
- 1333 if (result) {
- 1334 mGpsStatusListeners.put(listener, transport);
- 1335 }
1331行:
- 1228 GpsStatusListenerTransport(GpsStatus.Listener listener) {
- 1229 mListener = listener;
- 1230 mNmeaListener = null;
- 1231 }
GpsStatusListenerTransport类提供了几个方法如onGpsStarted,onGpsStopped,onFirstFix,onSvStatusChanged,onNmeaReceived等,而在这些方法中,会调用
mGpsHandler.sendMessage(msg),将消息发送给mListener,这样前面应用中实现的接口onGpsStatusChanged就会接收到消息了;
现在回到谁会调用这些方法来发送消息的问题上?当然是LocationManagerService.java,所以要将GpsStatusListenerTransport注册到服务中,这是在1332行中实现的,所以看
LocationManagerService.java的addGpsStatusListener方法:
- 1303 try {
- 1304 mGpsStatusProvider.addGpsStatusListener(listener);
- 1305 } catch (RemoteException e) {
- 1306 Slog.e(TAG, "mGpsStatusProvider.addGpsStatusListener failed", e);
- 1307 return false;
- 1308 }
mGpsStatusProvider是什么?
mGpsStatusProvider = gpsProvider.getGpsStatusProvider();
gpsProvider又是什么?
GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this);
看来要进入GpsLocationProvider类了,这个类是和GPS的JNI层打交道的地方,看他的getGpsStatusProvider方法:
- 343 public IGpsStatusProvider getGpsStatusProvider() {
- 344 return mGpsStatusProvider;
- 345 }
mGpsStatusProvider是:
- 296 private final IGpsStatusProvider mGpsStatusProvider = new IGpsStatusProvider.Stub() {
- 297 public void addGpsStatusListener(IGpsStatusListener listener) throws RemoteException {
- 298 if (listener == null) {
- 299 throw new NullPointerException("listener is null in addGpsStatusListener");
- 300 }
- 301
- 302 synchronized(mListeners) {
- 303 IBinder binder = listener.asBinder();
- 304 int size = mListeners.size();
- 305 for (int i = 0; i < size; i++) {
- 306 Listener test = mListeners.get(i);
- 307 if (binder.equals(test.mListener.asBinder())) {
- 308
- 309 return;
- 310 }
- 311 }
- 312
- 313 Listener l = new Listener(listener);
- 314 binder.linkToDeath(l, 0);
- 315 mListeners.add(l);
- 316 }
- 317 }
看来是实现了IGpsStatusProvider接口的一个服务类啊,所以1304行就是调用这里297行的addGpsStatusListener方法把客户端LocationManager中的listener添加到这里来啊。
307行先判断listener是否已经添加,接着313行,new Listener,315行的mListeners是ArrayList类型,就是把313创建的Listener加到动态数组中。
想想看,在GpsStatusProvider类中肯顶在某个地方会遍历mListeners中的成员,以便回调里面的方法,将数据发送出去;也就是说存在某个机制,已经运行起来了?这是什么机制?
其实没有什么机制,只不过GpsStatusProvider类实现了reportStatus和reportSvStatus方法,这些方法会提供给JNI层,也就是JNI主动调用java层的方法?那什么时候调用呢,进入
JNI层看看就知道了:
method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "()V");//看名字就知道是对应java的reportSvStatus方法了
- 90 static void sv_status_callback(GpsSvStatus* sv_status)
- 91 {
- 92 JNIEnv* env = AndroidRuntime::getJNIEnv();
- 93 memcpy(&sGpsSvStatus, sv_status, sizeof(sGpsSvStatus));
- 94 env->CallVoidMethod(mCallbacksObj, method_reportSvStatus);
- 95 checkAndClearExceptionFromCallback(env, __FUNCTION__);
- 96 }
sv_status_callback则在函数指针数组中被赋值:
- 139 GpsCallbacks sGpsCallbacks = {
- 140 sizeof(GpsCallbacks),
- 141 location_callback,
- 142 status_callback,
- 143 sv_status_callback,
- 144 nmea_callback,
- 145 set_capabilities_callback,
- 146 acquire_wakelock_callback,
- 147 release_wakelock_callback,
- 148 create_thread_callback,
- 149 request_utc_time_callback,
- 150 };
GpsCallbacks类在libhardware/include/hardware/gps.h定义:
- 368 typedef struct {
- 369
- 370 size_t size;
- 371 gps_location_callback location_cb;
- 372 gps_status_callback status_cb;
- 373 gps_sv_status_callback sv_status_cb;
- 374 gps_nmea_callback nmea_cb;
- 375 gps_set_capabilities set_capabilities_cb;
- 376 gps_acquire_wakelock acquire_wakelock_cb;
- 377 gps_release_wakelock release_wakelock_cb;
- 378 gps_create_thread create_thread_cb;
- 379 gps_request_utc_time request_utc_time_cb;
- 380 } GpsCallbacks;
这里是HAL层主动调用JNI层的方法,看看是怎么回事,在JNI的android_location_GpsLocationProvider_is_supported中:
if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0)
就是这一句,把sGpsCallbacks的地址传递了给HAL层,这里的sGpsInterface当然是在经过
hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);
sGpsInterface = gps_device->get_gps_interface(gps_device);
之后得到的。
所以进入HAL层看看吧:
- 1300 static const GpsInterface qemuGpsInterface = {
- 1301 sizeof(GpsInterface),
- 1302 qemu_gps_init,
- 1303 qemu_gps_start,
- 1304 qemu_gps_stop,
- 1305 qemu_gps_cleanup,
- 1306 qemu_gps_inject_time,
- 1307 qemu_gps_inject_location,
- 1308 qemu_gps_delete_aiding_data,
- 1309 qemu_gps_set_position_mode,
- 1310 qemu_gps_get_extension,
- 1311 };
- 1312
- 1313 const GpsInterface* gps__get_gps_interface(struct gps_device_t* dev)
- 1314 {
- 1315 return &qemuGpsInterface;
- 1316 }
GpsInterface类的定义:
- 384 typedef struct {
- 386 size_t size;
- 391 int (*init)( GpsCallbacks* callbacks );
- 394 int (*start)( void );
- 397 int (*stop)( void );
- 400 void (*cleanup)( void );
- 403 int (*inject_time)(GpsUtcTime time, int64_t timeReference,
- 404 int uncertainty);
- 411 int (*inject_location)(double latitude, double longitude, float accuracy);
- 418 void (*delete_aiding_data)(GpsAidingData flags);
- 425 int (*set_position_mode)(GpsPositionMode mode, GpsPositionRecurrence recurrence,
- 426 uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time);
- 429 const void* (*get_extension)(const char* name);
- 430 } GpsInterface;
看到了没,看来不用多说,JNI调用了qemu_gps_init方法:
- 1198 qemu_gps_init(GpsCallbacks* callbacks)
- 1199 {
- 1201 GpsState* s = _gps_state;
- 1206 s->callbacks = *callbacks;
- 1208 g_status.status=GPS_STATUS_ENGINE_ON;
- 1210 s->callbacks.status_cb(&g_status);
- 1214 if (!s->init)
- 1215 gps_state_init(s);
- 1217 if (s->fd < 0)
- 1218 return -1;
- 1222 return 0;
- 1223 }
这样1206行就得到了JNI层的sv_status_callback结构体地址,然后就可以调用它了,什么时候调用啊?在线程中检测到串口有GPS数据上报了就会调用,在线程中解析GPS的GSV数据
后会调用r->callback.sv_status_cb( &(r->sv_status) ):
- 90 static void sv_status_callback(GpsSvStatus* sv_status)
- 91 {
- 92 JNIEnv* env = AndroidRuntime::getJNIEnv();
- 93 memcpy(&sGpsSvStatus, sv_status, sizeof(sGpsSvStatus));
- 94 env->CallVoidMethod(mCallbacksObj, method_reportSvStatus);
- 95 checkAndClearExceptionFromCallback(env, __FUNCTION__);
- 96 }
93行把数据保存到JNI层,94行调用JAVA层的reportSvStatus方法:
- 1209 private void reportSvStatus() {
- 1210
- 1211 int svCount = native_read_sv_status(mSvs, mSnrs, mSvElevations, mSvAzimuths, mSvMasks);
- 1212
- 1213 synchronized(mListeners) {
- 1214 int size = mListeners.size();
- 1215 for (int i = 0; i < size; i++) {
- 1216 Listener listener = mListeners.get(i);
- 1217 try {
- 1218 listener.mListener.onSvStatusChanged(svCount, mSvs, mSnrs,
- 1219 mSvElevations, mSvAzimuths, mSvMasks[EPHEMERIS_MASK],
- 1220 mSvMasks[ALMANAC_MASK], mSvMasks[USED_FOR_FIX_MASK]);
- 1221 } catch (RemoteException e) {
- 1222 Log.w(TAG, "RemoteException in reportSvInfo");
- 1223 mListeners.remove(listener);
- 1224
- 1225 size--;
- 1226 }
- 1227 }
- 1228 }
1211行它又调用JNI的native_read_sv_status,它不做别的事情,就是读取前面保存在HAL层的数据,因为前面HAL层只是把数据拷贝到JNI层的变量中:
- 346 static jint android_location_GpsLocationProvider_read_sv_status(JNIEnv* env, jobject obj,
- 347 jintArray prnArray, jfloatArray snrArray, jfloatArray elevArray, jfloatArray azumArray,
- 348 jintArray maskArray)
- 349 {
- 350
- 351
- 352 jint* prns = env->GetIntArrayElements(prnArray, 0);
- 353 jfloat* snrs = env->GetFloatArrayElements(snrArray, 0);
- 354 jfloat* elev = env->GetFloatArrayElements(elevArray, 0);
- 355 jfloat* azim = env->GetFloatArrayElements(azumArray, 0);
- 356 jint* mask = env->GetIntArrayElements(maskArray, 0);
- 357
- 358 int num_svs = sGpsSvStatus.num_svs;
- 359 for (int i = 0; i < num_svs; i++) {
- 360 prns[i] = sGpsSvStatus.sv_list[i].prn;
- 361 snrs[i] = sGpsSvStatus.sv_list[i].snr;
- 362 elev[i] = sGpsSvStatus.sv_list[i].elevation;
- 363 azim[i] = sGpsSvStatus.sv_list[i].azimuth;
- 364 }
- 365 mask[0] = sGpsSvStatus.ephemeris_mask;
- 366 mask[1] = sGpsSvStatus.almanac_mask;
- 367 mask[2] = sGpsSvStatus.used_in_fix_mask;
- 368
- 369 env->ReleaseIntArrayElements(prnArray, prns, 0);
- 370 env->ReleaseFloatArrayElements(snrArray, snrs, 0);
- 371 env->ReleaseFloatArrayElements(elevArray, elev, 0);
- 372 env->ReleaseFloatArrayElements(azumArray, azim, 0);
- 373 env->ReleaseIntArrayElements(maskArray, mask, 0);
- 374 return num_svs;
- 375 }
最终我们的应用也就在onGpsStatusChanged方法中得到了要处理的数据啦
2013.08.22续:
由于要做一个测试软件来测试GPS性能,但是多加了一个北斗的数据,android标准只支持1~32号星,大于32将无法校验该卫星是否用来定位。所以只能增加一个int型来保存北斗的校验值,具体修改的地方如下:
1. hardware/libhardware中:
- diff --git a/include/hardware/gps.h b/include/hardware/gps.h
- index 69bfd50..895ee4f 100755
- --- a/include/hardware/gps.h
- +++ b/include/hardware/gps.h
- @@ -298,6 +298,11 @@ typedef struct {
- * were used for computing the most recent position fix.
- */
- uint32_t used_in_fix_mask;
- +
- +
-
-
- + uint32_t bd_used_in_fix_mask;
- } GpsSvStatus;
2.beidou_gps.c中:
- diff --git a/hardware/libhardware/gps/beidou_gps.c b/hardware/libhardware/gps/beidou_gps.c
- index 131a16e..d6001f9 100644
- --- a/hardware/libhardware/gps/beidou_gps.c
- +++ b/hardware/libhardware/gps/beidou_gps.c
- - if(!is_beidou)
- + if(!is_beidou){
- r->sv_status.used_in_fix_mask = 0ul;
- + r->sv_status.bd_used_in_fix_mask = 0ul;
- + }
- D("\n");
- for (i = 3; i <= 14; ++i){
-
- @@ -571,9 +573,13 @@ nmea_reader_parse( NmeaReader* r )
- int prn = str2int(tok_prn.p, tok_prn.end);
- D("gsa,prn=%d,",prn);
- if (prn > 0){
- - r->sv_status.used_in_fix_mask |= (1ul << ( prn-1));
- - r->sv_status_changed = 1;
- + if(is_beidou){
- + D("sclu %d, prn=%d", __LINE__, prn);
- + r->sv_status.bd_used_in_fix_mask |= (1ul << ( prn-1));
- + }else
- + r->sv_status.used_in_fix_mask |= (1ul << ( prn-1));
-
- + r->sv_status_changed = 1;
- }
3.frameworks/base中:
- diff --git a/location/java/android/location/GpsStatus.java b/location/java/android/location/GpsStatus.java
- index 4af55a6..73e3bcc 100644
- --- a/location/java/android/location/GpsStatus.java
- +++ b/location/java/android/location/GpsStatus.java
- @@ -18,6 +18,7 @@ package android.location;
-
- import java.util.Iterator;
- import java.util.NoSuchElementException;
- +import android.util.Log;
-
-
-
-
-
- synchronized void setStatus(int svCount, int[] prns, float[] snrs,
- float[] elevations, float[] azimuths, int ephemerisMask,
- - int almanacMask, int usedInFixMask) {
- + int almanacMask, int usedInFixMask, int bdusedInFixMask) {
- int i;
-
- for (i = 0; i < mSatellites.length; i++) {
- mSatellites[i].mValid = false;
- }
- -
- + Log.e("sclu", "ephemeris = " + Integer.toBinaryString(ephemerisMask) + ", almanac = " + Integer.toBinaryString(almanacMask) + ", usedinfix = " + Intege
- for (i = 0; i < svCount; i++) {
- +
- int prn = prns[i] - 1;
- - int prnShift = (1 << prn);
- + int prnShift;
- + if(prns[i] <= 32)
- + prnShift = (1 << (prn));
- + else
- + prnShift = (1 << (prn - 100));
- if (prn >= 0 && prn < mSatellites.length) {