1. 程式人生 > >Android GPS學習筆記—HAL實現

Android GPS學習筆記—HAL實現

        HAL的全稱是Hardware Abstraction Layer, 即硬體抽象層。

        HAL層是介於Android核心與上層之間抽象出來的一層結構,它是對linux驅動的一個封裝,對上層提供統一介面,上層應用不必知道下層是如何實現的,它遮蔽了底層的實現細節。

           1. HAL的由來

        Android的HAL是為了保護一些硬體提供商的智慧財產權而提出的,是為了避開linux的GPL束縛。思路是把控制硬體的動作都放到了Android HAL中,而linux driver僅僅完成一些簡單的資料互動作用,甚至把硬體暫存器空間直接對映到user space。而Android是基於Aparch的license,因此硬體廠商可以只提供二進位制程式碼,所以說Android只是一個開放的平臺,並不是一個開源的平臺。也許也正是因為Android不遵從GPL,所以Greg Kroah-Hartman才在2.6.33核心將Andorid驅動從linux中刪除。GPL和硬體廠商目前還是有著無法彌合的裂痕。Android想要把這個問題處理好也是不容易的。

        總結下來,Android HAL存在的原因主要有:

        (1). 並不是所有的硬體裝置都有標準的linux kernel的介面

        (2). KERNEL DRIVER涉及到GPL的版權。某些裝置製造商並不願意公開硬體驅動,所以才去用HAL方式繞過GPL。

        (3). 針對某些硬體,An有一些特殊的需求

        2. HAL的演進

        HAL以前是以module來被呼叫的。所謂module,就是將c檔案編譯成so檔案,然後在jni中載入呼叫。此種方式現在在原始碼的libhardware_legacy資料夾下。後來HAL的架構改變,變成了以stub的形式來被上層呼叫。這樣就有種面向物件的思想了。雖然也是編譯成so檔案然後載入,但是JNI是直接呼叫c物件。這種層次更清晰,而且更易於維護和擴充套件。

        3. 原始碼目錄

        hardware/libhardware/include/hardware/gps.h

        hardware/qcom/gps/loc_api/gps.c

        其中gps.h中定義了GPS相關的結構體介面,在“重要結構體及介面”中已經介紹,在此不再贅述。

        我們來看一下gps.c檔案:

        首先定義了gps裝置模組例項,下面的註釋很重要,說明了如何構建一個模組,這是Android中標準的構建模組寫法。

/**
 * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM
 * and the fields of this data structure must begin with hw_module_t
 * followed by module specific information.
 */
struct hw_module_t HAL_MODULE_INFO_SYM = {
    .tag = HARDWARE_MODULE_TAG,
    .module_api_version = 1,
    .hal_api_version = 0,
    .id = GPS_HARDWARE_MODULE_ID,
    .name = "loc_api GPS Module",
    .author = "Qualcomm USA, Inc.",
    .methods = &gps_module_methods,
};

這裡的id用來指定模組庫檔名的,methods指向gps.c檔案中的gps_module_methods:
static struct hw_module_methods_t gps_module_methods = {
    .open = open_gps
};

gps_module_methods定義了裝置的open函式為open_gps,我們來看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 = (struct gps_device_t *) malloc(sizeof(struct gps_device_t));

    if(dev == NULL)
        return -1;

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

此處可以看作是GPS裝置的初始化函式,在使用裝置前必須執行此函式。函式裡面指定了hw_device_tmodule成員,以及gps_device_tget_gps_interface成員。上層可通過gps_device_tget_gps_interface呼叫gps__get_gps_interface函式。gps__get_gps_interface的定義如下:

const GpsInterface* gps__get_gps_interface(struct gps_device_t* dev)
{
    return get_gps_interface();
}

get_gps_interface的實現是在gps/loc_api/Loc.cpp:
// for gps.c
extern "C" const GpsInterface* get_gps_interface()
{
    unsigned int target = TARGET_DEFAULT;
    loc_eng_read_config();

    target = loc_get_target();
    LOC_LOGD("Target name check returned %s", loc_get_target_name(target));

    int gnssType = getTargetGnssType(target);
    switch (gnssType)
    {
    case GNSS_GSS:
        //APQ8064
        gps_conf.CAPABILITIES &= ~(GPS_CAPABILITY_MSA | GPS_CAPABILITY_MSB);
        gss_fd = open("/dev/gss", O_RDONLY);
        if (gss_fd < 0) {
            LOC_LOGE("GSS open failed: %s\n", strerror(errno));
        }
        else {
            LOC_LOGD("GSS open success! CAPABILITIES %0lx\n",
                     gps_conf.CAPABILITIES);
        }
        break;
    case GNSS_NONE:
        //MPQ8064
        LOC_LOGE("No GPS HW on this target. Not returning interface.");
        return NULL;
    case GNSS_QCA1530:
        // qca1530 chip is present
        gps_conf.CAPABILITIES &= ~(GPS_CAPABILITY_MSA | GPS_CAPABILITY_MSB);
        LOC_LOGD("qca1530 present: CAPABILITIES %0lx\n", gps_conf.CAPABILITIES);
        break;
    }
    return &sLocEngInterface;
}
sLocEngInterface的定義如下:
// Defines the GpsInterface in gps.h
static const GpsInterface sLocEngInterface =
{
   sizeof(GpsInterface),
   loc_init,
   loc_start,
   loc_stop,
   loc_cleanup,
   loc_inject_time,
   loc_inject_location,
   loc_delete_aiding_data,
   loc_set_position_mode,
   loc_get_extension
};

sLocEngInterface指定了GpsInterface結構體的各個回撥函式,如啟動定位/取消定位等,這些回撥函式的實現均在Loc.cpp中實現。