现在的位置: 首页 > 综合 > 正文

android GPS HAL 回调函数实现

2013年10月06日 ⁄ 综合 ⁄ 共 5518字 ⁄ 字号 评论关闭

实现自己的GPS的HAL层,要实现gps.c文件,(按照Android系统的调用)参考http://blog.chinaunix.net/uid-25570748-id-184090.html分析的很好。

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,
};

static struct hw_module_methods_t gps_module_methods = {
    .open = open_gps
};

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));
    D("%s: called\n", __FUNCTION__);
    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_gps_interface;

    *device = (struct hw_device_t*)dev;
    return 0;
}

const GpsInterface* gps__get_gps_interface(struct gps_device_t* dev)
{
    D("%s: called\n", __FUNCTION__);
    return &sepGpsInterface;
}

static const GpsInterface  sepGpsInterface = {
    sizeof(GpsInterface),
    sep_gps_init,
    sep_gps_start,
    sep_gps_stop,
    sep_gps_cleanup,
    sep_gps_inject_time,
    sep_gps_inject_location,
    sep_gps_delete_aiding_data,
    sep_gps_set_position_mode,
    sep_gps_get_extension,
};

这里的GpsInterface定义如下,在hardware/libhardware/include/hardware/gps.h文件中

/** Represents the standard GPS interface. */
typedef struct {
size_t size;
int (*init)( GpsCallbacks* callbacks );
int (*start)( void );
int (*stop)( void );
void (*cleanup)( void );
int (*inject_time)(GpsUtcTime time, int64_t timeReference, int uncertainty);
int (*inject_location)(double latitude, double longitude, float accuracy);
void (*delete_aiding_data)(GpsAidingData flags);
int (*set_position_mode)(GpsPositionMode mode, GpsPositionRecurrence recurrence,
uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time);
const void* (*get_extension)(const char* name);
} GpsInterface;

/** 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;

比如说GpsInterface里面init函数,需要一个参数,callbacks,没有发现哪里有对回调函数的定义。有读了一遍别人的博客的分析http://blog.chinaunix.net/uid-25570748-id-184090.html
GPS服务启动的过程中,在JNI层会去初始化GPS
com_android_server_location_GpsLocationProvider.cpp文件中的ini函数

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; }

调用了GetGpsInterface去获取接口并初始化GPS

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) { sGpsInterface = get_gps_interface(); if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0) { sGpsInterface = NULL; return NULL; } } return sGpsInterface; }

GetGpsInterface里面也去调用了get_gps_interface(),而这个函数最早的地方便是isSupported()的这个函数。在获取了这个接口之后,使用sGpsInterface->init函数进行了初始化。原来是在这里注册了回调函数。

sGpsCallbacks是个全局变量,在com_android_server_location_GpsLocationProvider.cpp文件中

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,
};
然后,也有各个回调函数的实现

static void location_callback(GpsLocation* location)
{
    JNIEnv* env = AndroidRuntime::getJNIEnv();
    env->CallVoidMethod(mCallbacksObj, method_reportLocation, location->flags,
            (jdouble)location->latitude, (jdouble)location->longitude,
            (jdouble)location->altitude,
            (jfloat)location->speed, (jfloat)location->bearing,
            (jfloat)location->accuracy, (jlong)location->timestamp);
    checkAndClearExceptionFromCallback(env, __FUNCTION__);
}

static void status_callback(GpsStatus* status)
{
    JNIEnv* env = AndroidRuntime::getJNIEnv();
    env->CallVoidMethod(mCallbacksObj, method_reportStatus, status->status);
    checkAndClearExceptionFromCallback(env, __FUNCTION__);
}

static void sv_status_callback(GpsSvStatus* sv_status)
{
    JNIEnv* env = AndroidRuntime::getJNIEnv();
    memcpy(&sGpsSvStatus, sv_status, sizeof(sGpsSvStatus));
    env->CallVoidMethod(mCallbacksObj, method_reportSvStatus);
    checkAndClearExceptionFromCallback(env, __FUNCTION__);
}

static void nmea_callback(GpsUtcTime timestamp, const char* nmea, int length)
{
    JNIEnv* env = AndroidRuntime::getJNIEnv();
    // The Java code will call back to read these values
    // We do this to avoid creating unnecessary String objects
    sNmeaString = nmea;
    sNmeaStringLength = length;
    env->CallVoidMethod(mCallbacksObj, method_reportNmea, timestamp);
    checkAndClearExceptionFromCallback(env, __FUNCTION__);
}

static void set_capabilities_callback(uint32_t capabilities)
{
    LOGD("set_capabilities_callback: %ld\n", capabilities);
    JNIEnv* env = AndroidRuntime::getJNIEnv();
    env->CallVoidMethod(mCallbacksObj, method_setEngineCapabilities, capabilities);
    checkAndClearExceptionFromCallback(env, __FUNCTION__);
}

static void acquire_wakelock_callback()
{
    acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);
}

static void release_wakelock_callback()
{
    release_wake_lock(WAKE_LOCK_NAME);
}

static pthread_t create_thread_callback(const char* name, void (*start)(void *), void* arg)
{
    return (pthread_t)AndroidRuntime::createJavaThread(name, start, arg);
}

抱歉!评论已关闭.