转载请注明出处:http://blog.csdn.net/lbmygf/article/details/7063692
一 相关文件路径
Framework:
framework\base\services\java\com\android\server\systemServer.java
framework\services\java\com\android\server\LocationManagerService.java
frameworks\base\services\java\com\android\server\location\GpsLocationProvider.java
JNI: /framework/base/services/jni/com_android_server_location_GpsLocationProvider.cpp
HAL: /hardware/mx5x/gps/ //此处路径可能不一样
二 调用流程
1.Framework
systemServer.java:
public static final void init2() {
Slog.i(TAG, "Entered the Android system server!");
Thread thr = new ServerThread();
thr.setName("android.server.ServerThread");
thr.start();
}
init2函数中启动了一个线程来注册Android的诸多服务,如:Bluetooth Service,NetworkManagement Service,Notification Manager等,当然也包括Location Service。
在ServerThread线程的run函数中LocationManager服务的代码段如下:
class ServerThread extends Thread
{
......
try {
Slog.i(TAG, "Location Manager");
location = new LocationManagerService(context);
//实例化一个LocationManagerService对象。
ServiceManager.addService(Context.LOCATION_SERVICE, location);
} catch (Throwable e) {
Slog.e(TAG, "Failure starting Location Manager", e);
}
......
final LocationManagerService locationF = location;
......
if (locationF != null) locationF.systemReady();
//调用LocationManagerService对象的systemReady() 方法。
......
}
LocationManagerService.java
void systemReady() {
// we defer starting up the service until the system is ready
Thread thread = new Thread(null, this, "LocationManagerService");
thread.start();//start 线程
}
public void run()
{
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Looper.prepare();
mLocationHandler = new LocationWorkerHandler();
initialize();
Looper.loop();
}
private void initialize()
{
......
loadProviders();
......
}
private void loadProviders() {
synchronized (mLock) {
if (sProvidersLoaded) {
return;
}
// Load providers
loadProvidersLocked();
sProvidersLoaded = true;
}
}
private void loadProvidersLocked() {
try {
_loadProvidersLocked();
} catch (Exception e) {
Slog.e(TAG, "Exception loading providers:", e);
}
}
private void _loadProvidersLocked() {
if (GpsLocationProvider.isSupported())
......
}
GpsLocationProvider.java
public static boolean isSupported() {
return native_is_supported();
}
在GpsLocationProvider.java最后:
private static native boolean native_is_supported();
//声明一个native 函数
//native 是java关键字,表示它将由JNI完成。
private native boolean native_init();
private native void native_cleanup();
private native boolean native_set_position_mode(int mode, int recurrence, int min_interval, int preferred_accuracy, int preferred_time);
private native boolean native_start();
private native boolean native_stop();
2.JNI
com_android_server_location_GpsLocationProvider.cpp
static JNINativeMethod sMethods[] = {
/* name, signature, funcPtr */
{"class_init_native", "()V", (void *)android_location_GpsLocationProvider_class_init_native},
{"native_is_supported", "()Z", (void*)android_location_GpsLocationProvider_is_supported},
{"native_init", "()Z", (void*)android_location_GpsLocationProvider_init},
{"native_cleanup", "()V", (void*)android_location_GpsLocationProvider_cleanup},
{"native_set_position_mode", "(IIIII)Z", (void*)android_location_GpsLocationProvider_set_position_mode},
{"native_start", "()Z", (void*)android_location_GpsLocationProvider_start},
{"native_stop", "()Z", (void*)android_location_GpsLocationProvider_stop},
.........
};
int register_android_server_location_GpsLocationProvider(JNIEnv* env)
{
return jniRegisterNativeMethods(env, "com/android/server/location/GpsLocationProvider", sMethods, NELEM(sMethods));
}
这就把java层声明的native函数与JNI 函数关联起来。
static jboolean android_location_GpsLocationProvider_is_supported
(JNIEnv* env, jclass clazz)
{
return (sGpsInterface != NULL || get_gps_interface() != NULL);
//get_gps_interface()返回值不为空,开启gps服务
}
static const GpsInterface* get_gps_interface() {
int err;
hw_module_t* module;
const GpsInterface* interface = NULL;
err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);//得到模块信息
if (err == 0) {
hw_device_t* device;
err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);//打开模块
//得到gps device信息
if (err == 0) {
gps_device_t* gps_device = (gps_device_t *)device;
interface = gps_device->get_gps_interface(gps_device);
//得到的GPS HAL接口
}
}
return interface;
}
3、HAL
gpst.c
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; //填充JNI device
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, //JNI 根据此ID找到相应库文件
.name = "Goldfish GPS Module",
.author = "The Android Open Source Project",
.methods = &gps_module_methods,
};
到此如果gps HAL接口(qemuGpsInterface)不为空,则说明系统支持gps服务。
第一个流程到此结束,下面看下gps服务的开启
再回到 LocationManagerService.java
private void _loadProvidersLocked() {
......
if (GpsLocationProvider.isSupported())
......
updateProvidersLocked();
}
private void updateProvidersLocked() {
boolean changesMade = false;
for (int i = mProviders.size() - 1; i >= 0; i--) {
LocationProviderInterface p = mProviders.get(i);
boolean isEnabled = p.isEnabled();
String name = p.getName();
boolean shouldBeEnabled = isAllowedBySettingsLocked(name);
if (isEnabled && !shouldBeEnabled) {
updateProviderListenersLocked(name, false);
changesMade = true;
} else if (!isEnabled && shouldBeEnabled) {
updateProviderListenersLocked(name, true);
changesMade = true;
}
}
if (changesMade) {
mContext.sendBroadcast(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION));
}
}
private void updateProviderListenersLocked(String provider, boolean enabled)
{
......
LocationProviderInterface p = mProvidersByName.get(provider);
//LocationProviderInterface 为一个接口类,它的实现在
// GpsLocationProvider.java
//public class GpsLocationProvider implements LocationProviderInterface
// {...}
......
if (enabled) {
p.enable();
//开启gps服务,在GpsLocationProvider.java的实现
//很简单,发送一个gps enable 消息
if (listeners > 0) {
p.setMinTime(getMinTimeLocked(provider), mTmpWorkSource);
p.enableLocationTracking(true); // start gps apk时调用
}
} else {
p.enableLocationTracking(false);// 关闭gps服务
p.disable();//stop gps apk时调用
}
}
GpsLocationProvider.java
public void enable() {
synchronized (mHandler) {
sendMessage(ENABLE, 1, null);
}
}
private final class ProviderHandler extends Handler {
@Override
public void handleMessage(Message msg) {
int message = msg.what;
switch (message) {
case ENABLE:
if (msg.arg1 == 1) {
handleEnable();
} else {
handleDisable();
}
break;
case ENABLE_TRACKING:
handleEnableLocationTracking(msg.arg1 == 1);
break;
case REQUEST_SINGLE_SHOT:
handleRequestSingleShot();
break;
case UPDATE_NETWORK_STATE:
handleUpdateNetworkState(msg.arg1, (NetworkInfo)msg.obj);
break;
case INJECT_NTP_TIME:
handleInjectNtpTime();
break;
case DOWNLOAD_XTRA_DATA:
if (mSupportsXtra) {
handleDownloadXtraData();
}
break;
case UPDATE_LOCATION:
handleUpdateLocation((Location)msg.obj);
break;
case ADD_LISTENER:
handleAddListener(msg.arg1);
break;
case REMOVE_LISTENER:
handleRemoveListener(msg.arg1);
break;
}
......
}
}
};
private void handleEnable() {
if (mEnabled) return;
mEnabled = native_init();
// 定义 private native boolean native_init();
//调用JNI 的android_location_GpsLocationProvider_init方法
if (mEnabled) {
mSupportsXtra = native_supports_xtra();
if (mSuplServerHost != null) {
native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
}
if (mC2KServerHost != null) {
native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
}
} else {
Log.w(TAG, "Failed to enable location provider");
}
}
static jboolean android_location_GpsLocationProvider_init(JNIEnv* env, jobject obj)
{
const GpsInterface* interface = GetGpsInterface(env, obj);
if (!interface)
return false;
if (!sGpsDebugInterface)
sGpsDebugInterface =
(const GpsDebugInterface*)interface->get_extension(GPS_DEBUG_INTERFACE);
return true;
}
static const GpsInterface* GetGpsInterface(JNIEnv* env, jobject obj) {
// this must be set before calling into the HAL library
if (!mCallbacksObj)
mCallbacksObj = env->NewGlobalRef(obj);
if (!sGpsInterface) {
// this must be called in native_init
sGpsInterface = get_gps_interface();//得到HAL接口
if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0) {
sGpsInterface = NULL;
return NULL;
}
}
return sGpsInterface;
}
gps.c
static int qemu_gps_init(GpsCallbacks* callbacks)
{
gps_exit_flag = 0;
GpsState* s = _gps_state;
s->callbacks = *callbacks; // JNI传下回调函数
if (!s->init)
gps_state_init(s);
if (s->fd < 0)
{
return -1;
}
return 0;
}
static void
gps_state_init( GpsState* state )
{
state->init = 1;
state->control[0] = -1;
state->control[1] = -1;
state->fd = -1;
state->fd = gps_channel_open( &state->channel,
GPSHARDWARE_CHANNEL_NAME,
O_RDONLY );
//打开串口,设置波特率
if (state->fd < 0) {
LOGE("no gps hardware 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;
}
state->callbacks.create_thread_cb("qemu_gps", gps_state_thread, state);
//创建 gps服务线程
//for android 2.3
int fd_sleep, i = -1;
fd_sleep = open("/dev/gps_sleep", O_RDWR);
i = ioctl(fd_sleep, 111, 0);
close(fd_sleep);
D("gps state initialized ok");
return;
Fail:
gps_state_done( state );
}
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];
state->thread = pthread_self();
nmea_reader_init( reader );
// register control file descriptors for polling
epoll_register( epoll_fd, control_fd );
epoll_register( epoll_fd, gps_fd );
//注册监控control_fd gps_fd
D("gps thread running");
// now loop
for (;;) {
struct epoll_event events[2];
int ne, nevents;
nevents = epoll_wait( epoll_fd, events, 2, -1 );
//当control_fd或gps_fd 有数据写入时程序往下走,否则阻塞。
//init 到此结束
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;
do {
ret = read( fd, &cmd, 1 );
} while (ret < 0 && errno == EINTR);
if (cmd == CMD_QUIT) {
LOGD("gps thread quitting on demand");
goto Exit;
}
else if (cmd == CMD_START)
{
if (!started)
{
started = 1;
g_status.status = GPS_STATUS_SESSION_BEGIN ;
state->callbacks.status_cb(&g_status);
//上传gps状态
nmea_reader_set_callback( reader, state->callbacks.location_cb );
nmea_reader_set_sv_callback( reader, state->callbacks.sv_status_cb );
//传递回调函数,解码时reader作为参数传下去
}
}
else if (cmd == CMD_STOP)
{
if (started)
{
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) //gps serial
{
char buff[70];
for (;;)
{
if(gps_read_switch == 1 && gps_read_flags == 1) //add bu liu for gps start
{
started = 1;
g_status.status = GPS_STATUS_SESSION_BEGIN ;
state->callbacks.status_cb(&g_status);
nmea_reader_set_callback( reader, state->callbacks.location_cb );
nmea_reader_set_sv_callback( reader, state->callbacks.sv_status_cb );
gps_read_flags = 0;
}
if(gps_read_switch == 0) //add bu liu for gps stop
{
started = 0;
g_status.status = GPS_STATUS_SESSION_END;
state->callbacks.status_cb(&g_status);
nmea_reader_set_callback( reader,NULL );
nmea_reader_set_sv_callback( reader, NULL);
gps_read_flags == 1;
}
if(gps_exit_flag == 1) //add by liu for gps clearup
{
started = 0;
g_status.status = GPS_STATUS_ENGINE_OFF;
state->callbacks.status_cb(&g_status);
nmea_reader_set_callback( reader, NULL );
nmea_reader_set_sv_callback( reader, NULL);
gps_exit_flag = 0;
goto Exit;
}
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));
goto Exit;
}
for (nn = 0; nn < ret; nn++)
nmea_reader_addc( reader, buff[nn] );//数据解码
}
}
else
{
LOGE("epoll_wait() returned unkown fd %d ?", fd);
}
}
}
}
Exit:
return ;
}
===================================================================
static int qemu_gps_start()
{
GpsState* s = _gps_state;
if (!s->init) {
LOGE("%s: called with uninitialized state !!\n", __FUNCTION__);
return -1;
}
gps_read_switch = 1;
gps_read_flags = 1;
gps_state_start(s);
return 0;
}
gps_state_start( GpsState* s )
{
char cmd = CMD_START;
int ret;
do { ret=write( s->control[0], &cmd, 1 ); } //向control_fd 写入数据。
while (ret < 0 && errno == EINTR);
if (ret != 1)
LOGE("%s: could not send CMD_START command: ret=%d: %s",
__FUNCTION__, ret, strerror(errno));
}
=================================================================
Gps 数据格式
$GPGSA,A,2,03,06,14,19,,,,,,,,,41.7,38.7,15.6*07
$GPGSV,3,1,11,3,38,189,41,6,49,170,41,14,24,142,34,16,66,328,*73
$GPGSV,3,2,11,19,10,195,33,20,22,269,,23,23,322,,24,03,142,35*74
$GPGSV,3,3,11,29,07,040,,31,40,056,,32,33,246,,,,,*45
$GPRMC,063752.864,A,2238.2513,N,11400.5476,E,1.06,357.72,270610,,,A*6A
$GPGGA,063753.864,2238.2512,N,11400.5477,E,1,04,38.7,119.1,M,-3.2,M,,*74
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;
}
}
static void
nmea_reader_parse( NmeaReader* r )
{
int i;
NmeaTokenizer tzer[1];
Token tok;
SVinfos svInfo[4];
if (r->pos < 9) {
D("Too short. discarded.");
return;
}
nmea_tokenizer_init(tzer, r->in, r->in + r->pos); //去掉多余信息
tok = nmea_tokenizer_get(tzer, 0);
//获取前一字段信息
//$GPGGA,063754.864,2238.2511,N,11400.5477,E,1,04,38.7,119.1,M,-3.2,M,,*70
if (tok.p + 5 > tok.end) {//GPRXX
D("sentence id '%.*s' too short, ignored.", tok.end-tok.p, tok.p);
return;
}
// ignore first two characters.
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_hdop = nmea_tokenizer_get(tzer,8);
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);
nmea_reader_update_hdop(r, tok_hdop);
r->fix.size = sizeof(r->fix);
}
......
if (r->callback) {
r->callback( &r->fix ); //用回调函数上传数据
r->fix.flags = 0;
}
else {
D("no callback, keeping data until needed !");
}
if (r->sv_callback) {
r->sv_callback( &r->sv );//用回调函数上传数据
}
else {
D("no sv_callback, keeping data until needed !");
}
}
}
到此结束。