Recently, we have the opportunity to transplant a GPS device to our product. It is very easy for the GPS module to transplant itself. A friend who has developed GPS for wince or PC must be clear about it. He just reads the standard GPS data from the serial port, parses the data, and the application obtains the longitude and latitude, positioning time, and other information, convert it to a specific location on the map as needed or for other use.
Let's talk about the general hard GPS, its advantages are self-evident, relative"Base station positioning ",The accuracy is much higher, especially when the base station signal is poor. The disadvantage is that 1st cold start times are too slow !, There is also an antenna problem. I remember it was obvious that I tested GPS outside. In the afternoon, the signal was very good (it is estimated that the satellite was on my head) and it was very bad at night, really depressing --! Our colleagues used GPS in the past, but the results were not good. RF circuit processing is also very unprofessional. This is also the biggest disadvantage of hard GPS.
There is an agps solution. To be honest, I have not implemented this function. For more information about the android2.3gps interface, see GPS. h. The role of agps is to effectively solve the problem of slow cold start for 1st times (generally, the star Rate Table is pre-downloaded through the network ). 2. The agps can also use the base station to assist in positioning in areas with poor penetration ability in the room.
Well, this article introduces the GPS porting process. agps is still waiting for your help.
My environment is android2.3. GPS is similar to 2.2, but there are also major differences, especially the JNI and so hardware adaptation layers. Here I will record two major problems encountered when writing a dynamic library.
1. The JNI layer calls our dynamic library. For details, refer to the Code's own simulator gps_qemu.c.
Note the following:
In com_android_server_location_gpslocationprovider.cpp, when starting the GPS service, we first need to call the GPS interactive port through JNI.
Static const gpsinterface * get_gps_interface () {int err; hw_module_t * module; const gpsinterface * interface = NULL; err = hw_get_module (partition, (hw_module_t const **) & module ); // frankbibi acquisition module if (ERR = 0) {// frankbibi hw_device_t * device; err = module-> methods-> open (module, gps_hardware_module_id, & device ); // obtain the device if (ERR = 0) {// frankbibi //,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, ,,,,, gps_device_t * gps_device = (gps_device_t *) device; interface = gps_device-> get_gps_interface (gps_device); // -- frankbibi
// interface = gps_get_interface(); } } return interface;}
The corresponding libgps. So must be used in this way to call it correctly.
//frankBIBI
Static int open_xxgps (const struct plugin * 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-> common. close = (INT (*) (struct hw_device_t *) close_lights;Dev-> get_gps_interface = gps_get_hardware_interface; // Interaction
*device = (struct hw_device_t*)dev; return 0;}static struct hw_module_methods_t gps_module_methods = { .open = open_XXgps};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 = "XX GPS Module", .author = "The Android Open Source Project", .methods = &gps_module_methods,};//.......................................................................
Focus on thisDev-> get_gps_interface = gps_get_hardware_interface; // Interaction
In this case, the application will understand. It is similar to the stream interface.
static const GpsInterface XXGpsInterface = { XX_gps_init, XX_gps_start, XX_gps_stop, XX_gps_set_fix_frequency, XX_gps_cleanup, XX_gps_inject_time, XX_gps_delete_aiding_data, XX_gps_set_position_mode, XX_gps_get_extension,};const GpsInterface* gps_get_hardware_interface(){ return &XXGpsInterface;}
In this way, the interaction is OK. Next, initialization, GPS startup, data collection, data parsing, and data returned to JNI.
2. Here we will talk about the 2nd problems encountered. After initialization, the data is returned to the JNI layer, and libgps. So crashes. I believe that many of my colleagues who debug GPS in android2.3 will encounter this problem 1st times.
Why?
The specific error I encountered in this function
static voidnmea_reader_set_callback( NmeaReader* r, gps_location_callback cb ){ r->callback = cb; if (cb != NULL && r->fix.flags != 0) { D("%s: sending latest fix to new callback", __FUNCTION__); r->callback( &r->fix ); r->fix.flags = 0; }}
The call function is the gps_state_thread thread function, which is used to check whether the channel has control commands or data and then implement corresponding control.
else if (cmd == CMD_START) { if (!started) { D("gps thread starting location_cb=%p", state->callbacks.location_cb); started = 1; nmea_reader_set_callback( reader, state->callbacks.location_cb );//frankBIBI state->init = STATE_START;
Is there any ambiguity? Okay, let's release the callback function interface (GPS. h)
/** GPS callback structure. */typedef struct { /** set to sizeof(GpsCallbacks) */ size_t size; gps_location_callback location_cb; gps_status_callback status_cb; gps_sv_status_callback sv_status_cb; gps_nmea_callback nmea_cb; gps_set_capabilities set_capabilities_cb; gps_acquire_wakelock acquire_wakelock_cb; gps_release_wakelock release_wakelock_cb; gps_create_thread create_thread_cb;} GpsCallbacks;
Okay, R-> callback (& R-> fix); return data to JNI. Here we see the libgps. So crash picture, similar to the "3G switch" picture in my previous article.
Why?
Prompt in GPS. h
/** Callback with location information. * Can only be called from a thread created by create_thread_cb. */typedef void (* gps_location_callback)(GpsLocation* location);/** Callback with status information. * Can only be called from a thread created by create_thread_cb. */typedef void (* gps_status_callback)(GpsStatus* status);/** Callback with SV status information. * Can only be called from a thread created by create_thread_cb. */typedef void (* gps_sv_status_callback)(GpsSvStatus* sv_info);
Let's see how we created our gps_state_thread and create a thread in the gps_state_init function.
Pthread_create (& State-> thread, null, gps_state_thread, state )! = 0
Obviously, it cannot be associated with the feedback function of the JNI layer. OK, we will use create_thread_cb registered in JNI to create the thread we want!
//frankBIBI
if (state->callbacks.create_thread_cb( &state->thread, gps_state_thread, state )==0) { LOGE("could not create gps thread: %s", strerror(errno)); goto Fail;
// Adjust S-> callbacks = * callbacks to be initialized in advance
XX_gps_init(GpsCallbacks* callbacks)//
{ GpsState* s = _gps_state;//frankBIBIs->callbacks = *callbacks
if (!s->init)//
gps_state_init(s); if (s->fd < 0) return -1; // s->callbacks = *callbacks
return 0;}
About gpscallbacks *Callbacks ......CallbackExplanation:
When we perform GPS initialization, the static const gpsinterface * getgpsinterface (jnienv * ENV, jobject OBJ) function in com_android_server_location_gpslocationprovider.cpp "If (! Sgpsinterface | sgpsinterface-> Init (& sgpscallbacks )! = 0) "input the structure of the sgpscallbacks feedback function to our libgps. So initialization Registration !!
GpsCallbacks sGpsCallbacks = { sizeof(GpsCallbacks), location_callback, status_callback, sv_status_callback, nmea_callback, set_capabilities_callback, acquire_wakelock_callback, release_wakelock_callback, create_thread_callback,};
Well, libgps. So has these two problems. In this way, you can
GpsCallbacks sGpsCallbacks = { sizeof(GpsCallbacks), location_callback, status_callback, sv_status_callback, nmea_callback, set_capabilities_callback, acquire_wakelock_callback, release_wakelock_callback, create_thread_callback,};
Using these callback functions, data and information can be returned to JNI to fill in the GPS interface data. The other part can be completed by referring to the simulator that comes with the source code.
Our hardware adaptation layer is here first.
-------------------------- Hope there is an error. Please give me some advice. Thank you.