移动云

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: 活动 交友 discuz
查看: 4008|回复: 0

Android GPS代码分析

[复制链接]
发表于 2012-2-23 11:26:39 | 显示全部楼层 |阅读模式
几个主要的文件及目录:
frameworks/base/location/* (client部分)
frameworks/base/core/jni/android_location_GpsLocationProvider.cpp (JNI 部分)
frameworks/base/services/java/com/android/serverLocationManagerService.java(server 部分)
hardware/libhardware_legacy/gps/* (hardware 接口部分)


一是:控制通道,也就是由app层发起的比如enable或disable的控制命令。
example代码调用LocationManager.java ,再通过IPC来实现真正的调用。LocationManager.java 主要负责通信。具体的实现在LocationManagerService.java中。
接口文件是ILocationManager.aidl。在service中根据provider来创建了一个GpsLocationProvider.java,并通过JNI调 android_location_GpsLocationProvider.cpp,该文件再通过GPSInterface来调用硬件的具体实现代码。
二是: enable后的Location数据和状态上报。对于数据的上报过程,主要就是关注几个callback函数。主要代码分析如下:
在 GpsLocationProvider.java文件中enable()一个GpsLocationProvider时,会启动一个 GpsEventThread,该线程主要就是调用了native_wait_for_event();通过JNI调用到了 anroid_location_GpsLocationProvider.cpp中的 android_location_GpsLocationProvider_wait_for_event();而该event的触发是由来自硬件驱动 Location数据包的上报,底层的硬件驱动程序会把raw gps data通过pipe或其他的方式,送出来,这个要看gps驱动的实现了,我们通过自己实现的GpsInterface 来解析raw gps data并调用loaction_callback()来触发event并copy Location数据,等待到event后再调用GpsLocationProvider.java中的reportLocation()上报Location.

除了框架代码外,我们自己需要实现的代码也分为两块,一个是app层的代码,app层我也提供一个简单的代码例子,请参考以下代码:
public class LocationSample extends Activity implements LocationListener {

        private LocationManager lm;

        public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);

        lm.requestLocationUpdates(LocationManager.GPS_PROVIDER,1l,1l,this);
        }

        public void onLocationChanged(Location location) {
                // TODO Auto-generated method stub
        Log.d(TAG,"location: ");
        }

        public void onProviderDisabled(String provider) {
                // TODO Auto-generated method stub
                Log.d(TAG,"provider disable");
        }

        public void onProviderEnabled(String provider) {
                // TODO Auto-generated method stub
                Log.d(TAG,"provider enable");
        }
        public void onStatusChanged(String provider, int status, Bundle extras) {
                // TODO Auto-generated method stub
        Log.d(TAG,"status changed");
        }
}
另外一部分就是hardware/libhardware_legacy/gps 部分的实现,这个主要就是实现一个gps.h里面的几个数据结构:
typedef struct {
        gps_location_callback location_cb;
        gps_status_callback status_cb;
        gps_sv_status_callback sv_status_cb;
} GpsCallbacks;

typedef struct {
    int   (*init)( GpsCallbacks* callbacks );
    int   (*start)( void );
    int   (*stop)( void );
    void  (*set_fix_frequency)( int frequency );
    void  (*cleanup)( void );
    int   (*inject_time)(GpsUtcTime time, int64_t timeReference,
                         int uncertainty);
    void  (*delete_aiding_data)(GpsAidingData flags);
   int   (*set_position_mode)(GpsPositionMode mode, int fix_frequency);
    const void* (*get_extension)(const char* name);
} GpsInterface;

typedef struct {
    uint16_t        flags;
    double          latitude;
    double          longitude;
    double          altitude;
    float           speed;
    float           bearing;
    float           accuracy;
    GpsUtcTime      timestamp;
} GpsLocation;
在GpsInterface->init()的时候要把上层的GpsCallbacks传进来,然后start后,从驱动那里poll获得gps raw data,并对raw data进行解析并填充GpsLocation数据结构,然后调用location_cb 上报location 数据。

//初始化的时候,得到GpsInterface,调用init,

static jboolean android_location_GpsLocationProvider_init(JNIEnv* env, jobject obj)
{
    if (!sGpsInterface)
        sGpsInterface = gps_get_interface();
    return (sGpsInterface && sGpsInterface->init(&sGpsCallbacks) == 0);
}


GpsCallbacks sGpsCallbacks = {
    location_callback,
    status_callback,
    sv_status_callback,
};

//并且打开串口,注册sGpsCallbacks
qemu_gps_init(GpsCallbacks* callbacks)
   ----> GpsState*  s = _gps_state;
   ----> gps_state_init(s);
   ----> s->callbacks = *callbacks;

//打开串口,创建线程
gps_state_init( GpsState*  state )
   -----> state->fd = qemu_channel_open_gps
   -----> pthread_create( &state->thread, NULL, gps_state_thread, state )
   
static void location_callback(GpsLocation* location)
{
    pthread_mutex_lock(&sEventMutex);

    sPendingCallbacks |= kLocation;
    memcpy(&sGpsLocation, location, sizeof(sGpsLocation));

    pthread_cond_signal(&sEventCond); //同步西面的函数
    pthread_mutex_unlock(&sEventMutex);
}


//下面这个函数就是由上层的 java调用的,并且等待底层的硬件发送数据,其中由EventCond同步
static void android_location_GpsLocationProvider_wait_for_event(JNIEnv* env, jobject obj)
{
    pthread_mutex_lock(&sEventMutex);
    pthread_cond_wait(&sEventCond, &sEventMutex);
   
    // copy and clear the callback flags
    int pendingCallbacks = sPendingCallbacks;
    sPendingCallbacks = 0;
   
    // copy everything and unlock the mutex before calling into Java code to avoid the possibility
    // of timeouts in the GPS engine.
    memcpy(&sGpsLocationCopy, &sGpsLocation, sizeof(sGpsLocationCopy));
    memcpy(&sGpsStatusCopy, &sGpsStatus, sizeof(sGpsStatusCopy));
    memcpy(&sGpsSvStatusCopy, &sGpsSvStatus, sizeof(sGpsSvStatusCopy));
    pthread_mutex_unlock(&sEventMutex);   

    if (pendingCallbacks & kLocation) {
        env->CallVoidMethod(obj, method_reportLocation, sGpsLocationCopy.flags,
                (jdouble)sGpsLocationCopy.latitude, (jdouble)sGpsLocationCopy.longitude,
                (jdouble)sGpsLocationCopy.altitude,
                (jfloat)sGpsLocationCopy.speed, (jfloat)sGpsLocationCopy.bearing,
                (jfloat)sGpsLocationCopy.accuracy, (jlong)sGpsLocationCopy.timestamp);
    }
    if (pendingCallbacks & kStatus) {
        env->CallVoidMethod(obj, method_reportStatus, sGpsStatusCopy.status);
    }  
    if (pendingCallbacks & kSvStatus) {
        env->CallVoidMethod(obj, method_reportSvStatus);
    }
    if (pendingCallbacks & kXtraDownloadRequest) {   
        env->CallVoidMethod(obj, method_xtraDownloadRequest);
    }
    if (pendingCallbacks & kDisableRequest) {
        // don't need to do anything - we are just poking so wait_for_event will return.
    }
}

//hardware 那部分有个线程gps_state_thread 一直在读串口的内容并进行解析,最后解析到location的信息
由cpp文件的GpsCallbacks sGpsCallbacks = { location_callback....}同步上层的线程

gps_state_thread
        ----->nmea_reader_addc
               ----->nmea_reader_parse
                          ------> location_callback
                               ------->数据上报
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|管理员QQ:44994224|邮箱(t268studio@gmail.com)|Archiver|MCLOUDER

GMT+8, 2025-7-2 06:38 , Processed in 0.033822 second(s), 16 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表