android 2.3 gps流程分析

转载请注明出处: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 !");

       }

    }

}

到此结束。

转载请注明出处: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 !");

       }

    }

}

到此结束。

猜你喜欢

转载自blog.csdn.net/caoliang0921/article/details/7872302
2.3
今日推荐